While we’re on this topic, if a call :Play on two different audios consecutively, do they begin playback as soon as the method is called (meaning one will be slightly offset) or are they scheduled to begin at the exact same time?
Without taking any special steps, they begin playing on the next mix – so not immediately. While the audio engine uses a samplerate of 48kHz, it chunks that up into larger buffers, typically 512 samples at a time. Every few milliseconds (512/48000 → 10.6 ms) there will be a mixer step that produces a chunk of audio.
Note, however, mixer steps don’t usually align with your framerate, and the mixer is running at the same time as your code.
So even though they don’t begin immediately, it’s still possible for a script like this
audio1:Play()
audio2:Play()
to get unlucky, and have a mixer update occur in-between those two lines of code – that would put your two playbacks several milliseconds apart from one another.
I may end up needing to support a system where two seperate audios are used for the left and right channels, but I’m not sure if its possible to keep them synchronized to the sample.
We recently added sample-accurate pre-planning support to AudioPlayer’s Play/Stop methods, so you can achieve this by reworking the above code:
local SoundService = game:GetService("SoundService")
local now = SoundService:GetMixerTime()
--[[
You can probably make this preplanning time smaller,
it only needs to be big enough to guarantee
that the audio engine sees the whole plan,
before it needs to start playing any of it.
--]]
local preplanningTime = 0.1
local startTime = now + preplanningTime
assert(SoundService:GetMixerTime() < startTime) -- diagnostic, can be removed
audio1:Play(startTime)
assert(SoundService:GetMixerTime() < startTime) -- diagnostic, can be removed
audio2:Play(startTime)