From a7e56d727d2a56c297785769a6b029c3ebd82f38 Mon Sep 17 00:00:00 2001 From: jgk Date: Mon, 5 Apr 2021 12:55:52 +0200 Subject: [PATCH] Haddock --- src/Sound.hs | 43 +++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/src/Sound.hs b/src/Sound.hs index 703b44152..c5b4c6274 100644 --- a/src/Sound.hs +++ b/src/Sound.hs @@ -2,8 +2,10 @@ Module : Sound Description : Channel selection and storage -This module checks for empty channels and plays sounds on them, using data chunks loaded into an IntMap, -and sound specifications of type 'Sound' loaded into a Map. +This module checks for empty channels and plays sounds on them. +It uses data chunks loaded into an IntMap to determine the actual sounds played, +and sound specifications of type 'Sound' loaded into a Map to +keep track of which sounds are playing. Uses SDL.Mixer. -} module Sound @@ -18,11 +20,19 @@ import Control.Monad import Control.Lens {- | Play sounds from a list of indices. -Each sound is played once if there is a free channel. +Each sound starts playing (and will not repeat) if there is a free channel. +Use this if you don't care about timing, overlapping, fading, etc. -} playSoundQueue :: SoundData a -> [Int] -> IO () playSoundQueue sd ns = forM_ ns $ \n -> playIfFree (_loadedChunks sd IM.! n) Mix.Once +{- | Start playing new sounds and update sound specifications. +I think that this expects that unfinished sounds get passed forwards within the Map, to be rethought: +there may be a leak in the current typical usage. + -} +playAndUpdate :: Ord a => M.Map a Sound -> SoundData a -> IO (SoundData a) +playAndUpdate new sd = playSounds $ over playingSounds (updatePlaying new) sd + {- | Given a chunk, attempt to play this on a free channel a given number of times. Returns 'Just' the channel if succeeds. -} @@ -44,23 +54,24 @@ playSoundIfFree c s = case _soundTime s of f :: Maybe Mix.Channel -> Maybe Sound f = fmap ( \chan -> s & soundChannel ?~ chan) -{- Stop a channel if it was playing. +{- | Stop a channel if it was playing. Always returns 'IO' 'Nothing'. -} haltMaybe :: Maybe Mix.Channel -> IO (Maybe Sound) haltMaybe (Just x) = Mix.halt x >> return Nothing haltMaybe Nothing = return Nothing -{- Play a sound according to it's specification. +{- | Play a sound according to it's specification. Logic: check if sound is playing: - - If so, decrement timers, and/or stop playing and remove - - If not, check if there is free channel: - - If so, start playing - - If not, remove sound. + 1. If so, decrement timers, and/or stop playing and remove + 2. If not, check if there is free channel: + + * If so, start playing + * If not, remove sound. -} -playSound :: SoundData a -> Sound -> IO (Maybe Sound) -playSound sd s = case _soundChannel s of +updateOrStartSound :: SoundData a -> Sound -> IO (Maybe Sound) +updateOrStartSound sd s = case _soundChannel s of Just i -> case _soundTime s of Just t | t > 0 -> return $ Just $ set soundTime (Just $ t - 1) s | otherwise -> haltMaybe (_soundChannel s) @@ -70,14 +81,14 @@ playSound sd s = case _soundChannel s of ) Nothing -> playSoundIfFree (_loadedChunks sd IM.! _soundType s) s -{- Play all sounds and create new sound data. +{- | Play all sounds and create new sound data. -} playSounds :: SoundData a -> IO (SoundData a) playSounds sd = do - newSounds <- mapM (playSound sd) (_playingSounds sd) + newSounds <- mapM (updateOrStartSound sd) (_playingSounds sd) return $ sd & playingSounds .~ M.mapMaybe id newSounds -{- Update sound specifications by overwriting an old Map with a new Map. +{- | Update sound specifications by overwriting an old Map with a new Map. Copies any information about channels from the old Map to the new Map. -} updatePlaying :: Ord a => M.Map a Sound -> M.Map a Sound -> M.Map a Sound @@ -85,7 +96,3 @@ updatePlaying new old = M.unionWith f new old where f newSound oldSound = newSound {_soundChannel = _soundChannel oldSound} -{- Start playing new sounds and update sound specifications. - -} -playAndUpdate :: Ord a => M.Map a Sound -> SoundData a -> IO (SoundData a) -playAndUpdate new sd = playSounds $ over playingSounds (updatePlaying new) sd