This code wraps sounds in a type and records the last time a particular sound was played. If the last time the sound was played was only a few milliseconds ago, it doesn't play the sound. I set it to only a few milliseconds because my goal wasn't simply to avoid having sounds be loud, but instead to avoid the flanging effect you get when two identical sounds are played just milliseconds apart, and the way sounds are louder when repeated soon after one another. You can increase the delay if it isn't long enough for your tastes. I set it to what worked well in my Lego game.
Type Sound Global List:TList = CreateList() Global Path$ = "sfx" Global Volume_SFX# = 1.0 Global Volume_Music# = 1.0 Global MusicChannel:TChannel Global MusicTrack% = -1 Field _TSound:TSound Field _Looping% Field _LastPlayTime% ' ------------------------------------------------------------------------------------------------------------------------------------------------------- ' This method loads a sound. ' Specifying Null for Url will create a null sound which will do nothing if played. This is useful for creating placeholder sound instances. ' ------------------------------------------------------------------------------------------------------------------------------------------------------- Function Load:Sound(Url:Object, Loop%=False) Local NS:Sound NS = New Sound NS._TSound = LoadSound(Url, Loop) If (NS._TSound = Null) And (Url <> Null) Then RuntimeError("Error in Sound.Load() : ''" + String(Url) + "'' failed to load. Please reinstall the game.") NS._Looping = Loop List.AddLast(NS) Return NS End Function ' ------------------------------------------------------------------------------------------------------------------------------------------------------- ' Volume# allows you to set the sound's volume. ' Rate# allows you to adjust the speed at which the sound is played back up or down. ' ------------------------------------------------------------------------------------------------------------------------------------------------------- Method Play:TChannel(Volume#=1.0, Rate#=1.0) Local Channel:TChannel If _TSound = Null Then Return Null If Volume# < 0 Then Volume# = 0 If Volume# > 1 Then Volume# = 1 ' If the timer has looped, or this sound wasn't played too recently... If (_LastPlayTime > MilliSecs()) Or (MilliSecs() > (_LastPlayTime + 60)) ' Note: ' If any sounds are looped, we'll need to create a channel type to hold the currently active channels and so we can alter their volume when ' the sound effects volume slider is moved. ' Get sound ready to play. Channel = CueSound(_TSound) ' Set sound volume and pitch. Channel.SetVolume(Volume_SFX#*Volume#) Channel.SetRate(Rate#) ' Start playing sound. Channel.SetPaused(False) ' Record the time at which this sound was played so that we can avoid playing the same sound more than once in quick succession. _LastPlayTime = MilliSecs() Return Channel EndIf End Method End Type ' ------------------------------------------------------------------------------------------------------------------------------------------------------- ' This function loads all the sounds the game needs. ' ------------------------------------------------------------------------------------------------------------------------------------------------------- Global SOUND_MouseClick:Sound Global SOUND_HighlightFruit:Sound Global SOUND_PickFruit:Sound Global SOUND_UnpickFruit:Sound Global SOUND_SwapFruit:Sound Function LoadSounds() SOUND_MouseClick = Sound.Load(Sound.Path$ + "mouseclick.wav") SOUND_HighlightFruit = Sound.Load(Sound.Path$ + "highlightfruit.wav") SOUND_PickFruit = Sound.Load(Sound.Path$ + "pickfruit.wav") 'SOUND_UnpickFruit = Sound.Load(Sound.Path$ + "unpickfruit.wav") SOUND_SwapFruit = Sound.Load(Sound.Path$ + "swapfruit.wav") End Function