What's the best performing way to do a continuous sound that rises and falls in realtime, changing every frame in response to player actions?
No details needed, just the basics: a) Should it be a sample or a synth? And b) what API method is recommended?
(My ultimate aim is to have not just 1 but 3 or 4 tones that will come in and out of harmony as the player acts. But I don't want to slow down the visuals which are already taxing the CPU! If realtime pitch shifts can't be done efficiently, I have other ideas.)
A basic way to do this is with a synth. You can then play any note with synth:playNote(n) (n just being a number value). Here’s a simple program that changes the note with the crank:
local synth = playdate.sound.synth.new(playdate.sound.kWaveSquare)
local n = 1
function play()
synth:stop()
synth:playNote(n)
end
function playdate.update()
end
function playdate.cranked()
n = math.floor(playdate.getCrankPosition())
play()
end
As for samples vs synths, my hunch is that there won't be much difference (and above a threshold frequency, synths switch from the generator algorithm to a wavetable [i.e., sample] to avoid aliasing). Both should be pretty efficient. The MIDI Player demo uses synths and samples, playing maybe a dozen sounds simultaneously, and I don't think its CPU usage is very high.
Thanks! What about changing the pitch of an already-playing sound every frame? I don't want to keep re-triggering a new note, but rather a smooth rise and fall of a sound that just keeps going.
But all mentions of "pitch" in the Lua SDK docs seem to be about playing a single note. Is there an approach to do this?
I think you're looking for sampleplayer:setRate() and fileplayer:setRate(). From my own testing, the higher you set the sample rate the bigger the performance impact will be. You can kind of get around this by importing a higher pitched sample to begin with, and then use a lower range of values for setRate(). Also using mono samples will have much less impact on performance than stereo samples.