Setting rate plays original sound and the sound at the set rate

Issue:

  1. Launch a sound (sampleplayer or fileplayer) at rate 1
  2. then use setRate(0.5) and you will hear both sounds (rate 1 and rate 0.5). Same thing happens when you start with play(1,1) and then stop() + play(1,0.5).
  3. Also getRate gives always 1 with sampleplayer if you change the rate through play method (but it is correctly updated when using setRate).

Expected result:

  1. changing rate should change the rate of the current sample and not launch another one
  2. sampleplayer:getRate should give the correct rate

Code Sample (put in update loop). Test by pressing A then B:

if playdate.buttonIsPressed( playdate.kButtonA ) then

        fp = playdate.sound.sampleplayer.new( "sounds/Drumming Sticks" )

        fp:play(1,0.5)

    end

    if playdate.buttonIsPressed(playdate.kButtonB) then

        fp:stop()

        fp:play(1,1) -- you can hear both sound at rate 0.5 and at rate 1

    end


    if fp then

        gfx.drawText("speed: " ..  fp:getRate(), 5, 5) -- display always 1 (but it should display 0.5 when pressing A)

    end

You're using buttonIsPressed(), which means you're creating a new sampleplayer on each frame that the A button is held down — and this can be several frames even for a quick tap. Then you assign them all to the same variable (fp), so you're only calling stop() on the most recent player.

I would try using buttonJustPressed() instead, because it's guaranteed to return true at most once per button press.

Thanks. You are absolutely right, I should have used buttonJustPressed. I confirm that it fixes my sound overlap problem.

But getRate is still returning 1 when setting rate parameter to a different rate in play method:

fp = playdate.sound.sampleplayer.new( "sounds/Drumming Sticks" )
fp:play(1,0.5)

I believe that's as designed — you can either set a default rate for the player using setRate(), or you can pass one to play() to override the default just for that playback. Passing a rate to play() doesn't change the player's default rate, which is what's returned by getRate().

Ok I understand. Thanks for your explanation. Maybe that deserves better explanation in the documentation because there is no mention of default rate and current rate for current play.

Ah, nope, that's a bug. :frowning: If you use player:setRate() it correctly stores the value for subsequent getRate() calls, but if you give the rate argument in play() it doesn't. It's an easy fix, though! I'll push that now, hopefully get that into 1.13

Oh, I didn't quite grok what Dan was talking about there, thankfully he clarified in the issue I filed. setRate() sets the rate that gets played when you call play() without the rate argument. So if you do player:setRate(0.5) then player:play(1,2.0), player:getRate() should return 2.0 while the sample is playing (at 2x speed) and then 0.5 after it's done. There's a lot more going on here than I'd expected! Let me know if that jibes with what you're expecting and I'll make it work that way.

Yes it looks correct that way! Thanks.