Seamless audio looping please :) (and better ways to sync too)


As per subject. The DIY approach (using the finish event to restart playback) is super clunky in practice; it’s really no good unless there’s a silent bit at the start and end of your audio. It’s certainly unusable for most music. I’ve spent the last few hours experimenting with automated cross-fades between two instances of an audio object to try and hide the glitch but it’s just not reliable.

Ogg allows for metadata to be added to specify looped regions, which could help; but even if we had limitations like “your loop has to start and finish at Ogg page boundaries”, or “your loop must be a multiple of x samples or milliseconds”, that’d still be good.

In an ideal world, just a “looped” parameter/flag added to Z.Audio.Start() would be perfect :slight_smile:

Tagging some more stuff on this post. I’ve been struggling with audio sync today. Just simple test projects, like a visual metronome: import a track at known bpm, then flash a Plane on the beat. I’ve finally just about got it working consistently, but it took an on("frame") handler, checking how many real milliseconds have passed since I started playback, then scripting the flash.

Timelines don’t sync well - when you say “play”, there could be a few frames gone before it actually starts playing. Z.every(x) is somewhat unreliable; ask for an event to be fired off every 500ms and what you’ll actually get is 500, 516, 516, 507, 516, 508, 508 etc. It accumulates, so if you’re doing multiple things over time, you’re best to rely on Date().getTime() if you don’t want things to wander further and further out of time.

There’s still (sometimes) a frame or two delay between saying and it happening. It’s a bit inconsistent. Anything you can do to tighten that up would help. Wishlist:

  • looping (ha)
  • a way to query the current playback time of an audio track
  • more precise starting of playback, or a way to callback once playback’s started. If there’s a variable delay you can’t do anything about, maybe there’s a way you could fire an event at the point you know it has started. If that means we need to do additional work to preload/rewind/prepare, that’s fine
  • seeking would be nice; don’t know enough about Ogg to know if arbitrary seek times would be practical, but as long as it was consistent (eg seek requests get you to the nearest second - but they’ll always get you to that same point)

All this stuff relates to internally stored .OGG files - I haven’t started trying to stream or load from a URL yet, but this kinda audio/video sync thing is key to making rich experiences. If you want a beta tester, I’m yer man :wink:

This is my wee test project: audio_loop_tests.zpp (2.7 MB)

It’s untidy. But I’ve got the tick text flashing consistently and mostly accurately; the super-short timeline responsible for flashing the central square is started at exactly the same time each beat, but visibly wanders in and out of sync.