-- High level api for playing sounds (and background music) module Sound.SFML ( -- * PolySounds PolySound, newPolySound, freePolySound, triggerPolySound, -- * LoopedSounds LoopedSound, newLoopedSound, freeLoopedSound, startLoopedSound, stopLoopedSound, ) where import Data.IORef import Control.Monad import Foreign.Ptr import Sound.SFML.LowLevel -- * PolySounds -- | A PolySound allows you to trigger one sound multiple times. -- The played sounds will then overlap. -- (Internally, there will be multiple sound instances, that will -- be triggered one after the other. If there are not enough internal -- instances, sounds will be cut.) data PolySound = PolySound FilePath (Ptr SoundBuffer) [Ptr Sound] (IORef Int) instance Show PolySound where show (PolySound file _ _ _) = "PolySound " ++ show file -- | Loads a sound into memory. newPolySound :: FilePath -- ^ soundfile -> Int -- ^ number of internal sound instances. -> IO PolySound newPolySound path numberOfVoices = do buffer <- sfSoundBuffer_CreateFromFile path sounds <- forM [1 .. numberOfVoices] $ \ _ -> do sound <- sfSound_Create sfSound_SetBuffer sound buffer return sound ref <- newIORef 0 return $ PolySound path buffer sounds ref -- | Frees the memory allocated by a sound. Don't use the PolySound afterwards. freePolySound :: PolySound -> IO () freePolySound (PolySound _ buffer sounds _) = do sfSoundBuffer_Destroy buffer mapM_ sfSound_Destroy sounds -- | Trigger a sound triggerPolySound :: PolySound -> IO () triggerPolySound (PolySound _ _ sounds ref) = do i <- readIORef ref let i' = (i + 1) `mod` length sounds writeIORef ref i' sfSound_Play (sounds !! i) -- * LoopedSounds -- | LoopedSounds are sounds that will always loop. -- They can just be switched on and off. newtype LoopedSound = LoopedSound (Ptr Sound) deriving Show -- | Loads a sound into memory. newLoopedSound :: FilePath -> IO LoopedSound newLoopedSound path = do buffer <- sfSoundBuffer_CreateFromFile path sound <- sfSound_Create sfSound_SetBuffer sound buffer sfSound_SetLoop sound True return $ LoopedSound sound -- | Releases the allocated memory of a LoopedSound. -- Don't use the LoopedSound afterwards. freeLoopedSound :: LoopedSound -> IO () freeLoopedSound (LoopedSound ptr) = sfSound_Destroy ptr -- | Starts a looped sound. startLoopedSound :: LoopedSound -> IO () startLoopedSound (LoopedSound ptr) = sfSound_Play ptr -- | Stops a looped sound. stopLoopedSound :: LoopedSound -> IO () stopLoopedSound (LoopedSound ptr) = sfSound_Stop ptr -- * Music -- There is always only one music lpaying at a single time. -- | Loads and plays a music file once. -- playMusic :: FilePath -> IO () -- playMusic = error "playMusic" -- | Loads and plays a music file in a loop. -- Stops if the program ends or 'stopMusic' is called. -- playMusicLooped :: FilePath -> IO () -- playMusicLooped = error "playMusicLooped" -- | Stops any background music that is playing. -- stopMusic :: IO () -- stopMusic = error "stopMusic"