Calling setVolume(0.0) on a playdate.sound.fileplayer that is currently playing appears to pause the fileplayer.
I did not find anything in the documentation implying this is intended behavior, so my expectation would've been to see the fileplayer muted but continuing to process the loaded file.
With volume set to 0.0 as above, fileplayer:isPlaying() will continue to return true, but fileplayer:getOffset() will show the offset is not changing.
Simple repro script using main_theme.wav from PlaydateSDK/Examples/Level 1-1:
local pdFilePlayer <const> = playdate.sound.fileplayer
local fp <const> = pdFilePlayer.new("main_theme")
assert(fp ~= nil)
local inputHandlers = {
AButtonDown = function()
if fp:getVolume() > 0.0 then
fp:setVolume(0.0)
else
fp:setVolume(1.0)
end
end
}
playdate.inputHandlers.push(inputHandlers)
fp:play()
function playdate.update()
print(fp:getOffset())
print(fp:isPlaying())
end
With this script, pressing the A button causes the volume to change from 0.0 to 1.0 and back again, and the offset is continuously printed in the console.
While volume is at 0.0, the printed offset does not change, and one can clearly hear from the audio output that the song is paused and resumes from where it stopped when A is pressed again.
For a long time this was the oldest open issue in the tracker, from the Demon Quest season 1 game. They were fading tracks in and out and wanted them to stay in sync even when they weren't audible. I didn't like it because of the wasted overhead of constantly decoding multiple files from disk just to have the data thrown out, planned to come up with something where it would automatically jump to the correct offset when the track came back in, but never found the time and I think they wound up using the workaround of fading the tracks to volume 0.01 instead of 0.
Changing the default behavior would break existing games, but we could add a "continue when muted" flag you'd set to get this. Note that it would still pause if it was in a channel with volume set to zero, I'm pretty sure, since the player's render function wouldn't get called.
Have you tried using fileplayer:setOffset() to advance to the correct position before unpausing the audio?
That's exactly what I ended up doing as a workaround. My use case is the same as what you described from Demon Quest. I guess I would have to make sure to do it for channels as well.
Have you tried using fileplayer:setOffset() to advance to the correct position before unpausing the audio?
This technically works if I either specify a buffer size on creation (edit: or use the 0.25 second default buffer size, same thing) and add that into the setOffset() call (as this older bug report says to do), if I don't then the track audibly starts from a slightly different place (not sure if this is due to setOffset() latency). BUT, even with the buffer size factored in, when the fileplayer resumes I first hear notes from a different point in the track, until the fileplayer "catches up" and is then in sync again. If I had to guess, it may sound like it's playing what's in the buffer before it populates it again at the right offset (I may of course be completely off base here, having no other insight into the internals).
I didn't like it because of the wasted overhead of constantly decoding multiple files from disk just to have the data thrown out
I get that, and agree it's not ideal, but forcing this behavior into setVolume() feels a bit arbitrary, considering fileplayer:pause() exists separately (granted, perhaps it didn't early on), but more importantly at this point this is inconsistent with the interface for both sequences and sampleplayers, which simply get muted when the volume is set to 0. Perhaps even more importantly, if this is deliberate and was clearly documented in the API docs I would have spent less time chasing it down