SamplePlayer.setRateMod and an LFO

(SDK on Mac)

I want to have a very slow, subtle "warble" to a set of sample players. My thinking is I can use setRateMod on a sample player to make that happen. What actually happens is that the LFO does change the rate like I want, but after about 4 seconds it just stops.

I feel like I must be doing something wrong with the LFO object, but I'm not sure what. It's almost as if the LFO is causing the samplePlayer object to just stop playing.

local snd <const> = playdate.sound

function EnoTape:init(sampleList)
   if type(sampleList) == "string" then sampleList = {sampleList} end
   self:setSamples(sampleList)
   
   self.source = snd.sampleplayer.new(self.samples[self:getRandomIndex()])
   self.source:setRateMod(self:warbleLfo())
end

function EnoTape:warbleLfo()
   local lfo = snd.lfo.new(snd.kLFOTriangle)
   lfo:setRate(0.1) 
   lfo:setDepth(0.0125) 
   lfo:setCenter(1)
   return lfo
end

function EnoTape:play()
   self.source:play()
end

x = EnoTape("path/to/a/long/sample")
x.play() 

Thanks for the help!

As far as I can tell, this has been broken and unnoticed since four years ago when I added sample-accurate LFO timing. The render function sees that the LFO is going to change values in the middle of a frame, so it renders everything before that time with the first value then loops again and renders the rest with the new value. But after the first loop some other code thinks it stopped short because it used up all the data so it stops playing. What a dumb mistake, so embarrassing. :frowning:

If you use kLFOSine instead it will work and hopefully give you the effect you're looking for. I've filed this and I'll get it fixed as soon as I can. Thanks for catching this!

1 Like

Thank's for the response!

Honestly, this is such a wild edge case. I'm glad to have been helpful.