Stopping a sound effect

Started by alexgleason, October 21, 2018, 07:17:12 PM

Previous topic - Next topic
Hi all, wondering if there's any way to do this or any plans to add it? I have an item that should make a continuous sound until stopped.
RIP Aaron Swartz

If your sound has a short loop then it should simply be a matter of having a timer looping continuously until stopped that plays the sound over and over.

If the sound has a long loop this could be problematic because once you stop the timer the sound would still continue playing until the end of the loop.

Quote from: llamazing on October 21, 2018, 07:35:09 PM
If your sound has a short loop then it should simply be a matter of having a timer looping continuously until stopped that plays the sound over and over.

If the sound has a long loop this could be problematic because once you stop the timer the sound would still continue playing until the end of the loop.

It's a vacuum sound, with multiple phases as the power of the vacuum increases the longer you hold the button. Guess I'm gonna try breaking my sfx into tiny pieces and use timers. Thanks!
RIP Aaron Swartz

Not sure if this is feasible, but the reason a vacuum sound sounds higher or lower is the speed of the rotation. Idk if it'd work, but if you decreased the time between each vacuum sample being played, the pitch would raise. But we're talking playing this sample every 1-3ms, which might likely break something. But it's worth a shot because you could increase the frequency of the sound kind of realistically. Maybe.

Sooo, I tried both methods (Max's and llamazing's). I thought Max's idea was pretty bright but I was getting all kinds of audio buffer errors. It also had a choppy sound. Code was basically this:

Code ( lua) Select
function item:_play_sound()
  local speed = 390 / self._power
  sol.audio.play_sound("alex/vacuum_2")
  self._sound_timers[self._power] = sol.timer.start(self, speed, function()
    self._sound_timers[self._power] = nil
    self:_play_sound()
  end)
end


Maybe there was a way to make this work right, but I'm not sure. Anyway I ended up breaking it up into 3 different sounds and writing this monstrous code:

Code ( lua) Select
-- Handle repeating sfx
-- FIXME: Make this code not horrible!
-- See: https://gitlab.com/solarus-games/solarus/issues/1289
function item:_play_sound()
  if self._power == 1 and not self._sound_timers[1] then
    log("sfx start: Vacuum 1")
    sol.audio.play_sound("vacuum_1")
    self._sound_timers[1] = sol.timer.start(self, 180, function()
      self._sound_timers[1] = nil
      item:_play_sound()
    end)
  elseif self._power == 2 and not self._sound_timers[2] then
    log("sfx start: Vacuum 2")
    sol.audio.play_sound("vacuum_2")
    self._sound_timers[2] = sol.timer.start(self, 125, function()
      self._sound_timers[2] = nil
      item:_play_sound()
    end)
  elseif self._power == 3 and not self._sound_timers[3] then
    log("sfx start: Vacuum 3")
    sol.audio.play_sound("vacuum_3")
    self._sound_timers[3] = sol.timer.start(self, 125, function()
      self._sound_timers[3] = nil
      item:_play_sound()
    end)
  end
end


I may go back and encapsulate the repeating parts into a function, but this was bad code anyway. ::)

I also had to do this when the item command was released, which I don't totally understand.

Code ( lua) Select
  -- Set all sound timers to nil
  -- FIXME: I don't understand why looping through them didn't work
  self._sound_timers[1] = nil
  self._sound_timers[2] = nil
  self._sound_timers[3] = nil


Ultimately, _play_sound() is called whenever the vacuum's power level is changed, so that's nice. It syncs the sound up to the vacuum quite nicely. Each clip is also <200ms so it feels like a pretty immediate stop when you release the button.

Here's the full commit if anyone is interested: https://gitlab.com/voadi/voadi/commit/497699088b4db58860213ca3acc3577acd1dbd09
RIP Aaron Swartz