Первый вариант, использовать callback timeupdate, отслеживать приближение к концу, чтобы перематывать на начало. Минус этого метода состоит в том, что этот колбэк срабатывает редко и, каждое повторение будет неравной длины. Это может быть слышно. К тому же можно пропустить конец, потому что колбэк никогда на конечной точке не сработает.
Второй вариант, делать тоже самое с помощью reqest animation frame. Он срабатывать чаще, но тоже есть свои минусы. Если владыка закрыта на слабых устройствах Теоретически может вызываться реже. Но из практики могу сказать, что он работает лучше и услышать неровность по длительности почти невозможно.
В обоих случаях может быть такая ситуация: в односеккндном файле приходит колбэк с параметром 0,9799, а следующий уже 0. Т.е. минуя 1. Причина как раз в том, что колбэк генерируется периодически.
Третий вариант. Если вы делаете что-то, где важен реально ровный ритм (например, метроном), единственный выход читать audioBuffer, копировать его много раз, склеивать в один длинный массив и проигрывать этот длинный файл. Работает это быстро и очень точно.