Files
loop/src/Dodge/SoundLogic.hs
T

276 lines
7.5 KiB
Haskell

{- |
Module : Dodge.SoundLogic
Description : Messages to "Sound" backend
This module allows us to talk to the "Sound" module.
-}
module Dodge.SoundLogic (
-- * Manipulation of individual sounds
soundStart,
soundContinue,
soundContinueVol,
soundFromGeneral,
soundMultiFrom,
stopSoundFrom,
-- * helper to determine the angle of a sound given a world position
soundAngle,
-- * Manipulation of all sounds
haltSound,
resumeSound,
pauseSound,
module Dodge.SoundLogic.LoadSound,
) where
import Control.Lens
import Data.Int (Int16)
import qualified Data.Map as M
import Data.Maybe
import Dodge.Data.Universe
import Dodge.SoundLogic.LoadSound
import Geometry.Data
import Geometry.Vector
import Sound.Data
-- | Placeholder...
haltSound :: World -> World
haltSound w = w
-- | Placeholder...
pauseSound :: World -> World
pauseSound w = w
-- | Placeholder...
resumeSound :: Universe -> Universe
resumeSound w = w
soundWithStatusVolumeGeneral ::
-- | Volume factor, 0 - 1
Float ->
PlayStatus ->
-- | \"Creator\" of sound
SoundOrigin ->
-- | Position of sound
(World -> Point2) ->
-- | ID of sound to be played
SoundID ->
-- | Frames to play sound for, Nothing for until finished
Maybe Int ->
World ->
World
soundWithStatusVolumeGeneral vol status so fpos sType mtime w = w & toPlaySounds %~ M.insertWith f so sound
where
sound =
Sound
{ _soundChunkID = sType
, _soundTime = mtime
, _soundStatus =
SoundStatus
{ _playStatus = status
, _isLooping = isJust mtime
}
, _soundChannel = Nothing
, _soundAngDist = Just (a, floor (225 * (1 - vol)))
, _soundPos = fpos w
, _soundVolume = soundToVol sType * vol
, _soundVolumeFraction = vol
}
f _ s = s{_soundTime = mtime}
a = soundAngle (fpos w) w
soundWithStatusVolume ::
-- | Volume factor, 0 - 1
Float ->
PlayStatus ->
-- | \"Creator\" of sound
SoundOrigin ->
-- | Position of sound
Point2 ->
-- | ID of sound to be played
SoundID ->
-- | Frames to play sound for, Nothing for until finished
Maybe Int ->
World ->
World
soundWithStatusVolume vol status so pos = soundWithStatusVolumeGeneral vol status so (const pos)
--soundWithStatusVolume vol status so pos sType mtime w = w & toPlaySounds %~ M.insertWith f so sound
-- where
-- sound = Sound
-- { _soundChunkID = sType
-- , _soundTime = mtime
-- , _soundStatus = SoundStatus
-- {_playStatus = status
-- ,_isLooping = isJust mtime
-- }
-- , _soundChannel = Nothing
-- , _soundAngDist = Just (a,floor (225 * (1 - vol)))
-- , _soundPos = pos
-- , _soundVolume = soundToVol sType * vol
-- , _soundVolumeFraction = vol
-- }
-- f _ s = s {_soundTime = mtime }
-- a = soundAngle pos w
soundWithStatus ::
PlayStatus ->
-- | \"Creator\" of sound
SoundOrigin ->
-- | Position of sound
Point2 ->
-- | ID of sound to be played
SoundID ->
-- | Frames to play sound for, Nothing for until finished
Maybe Int ->
World ->
World
soundWithStatus = soundWithStatusVolume 1
soundStart ::
-- | \"Creator\" of sound
SoundOrigin ->
-- | Position of sound
Point2 ->
-- | ID of sound to be played
SoundID ->
-- | Frames to play sound for, Nothing for until finished
Maybe Int ->
World ->
World
soundStart = soundWithStatus ToStart
soundContinue ::
-- | \"Creator\" of sound
SoundOrigin ->
-- | Position of sound
Point2 ->
-- | ID of sound to be played
SoundID ->
-- | Frames to play sound for, Nothing for until finished
Maybe Int ->
World ->
World
soundContinue = soundWithStatus ToContinueStart
-- this needs to all be cleaned up, moved to general sounds
soundContinueVol ::
-- | volume
Float ->
-- | \"Creator\" of sound
SoundOrigin ->
-- | Position of sound
Point2 ->
-- | ID of sound to be played
SoundID ->
-- | Frames to play sound for, Nothing for until finished
Maybe Int ->
World ->
World
soundContinueVol vol = soundWithStatusVolume vol ToContinueStart
soundFromGeneral ::
-- | \"Creator\" of sound
SoundOrigin ->
-- | Position of sound
(World -> Point2) ->
-- | ID of sound to be played
SoundID ->
-- | Frames to play sound for, Nothing for until finished
Maybe Int ->
World ->
World
soundFromGeneral = soundWithStatusVolumeGeneral 1 ToStart
--soundFromGeneral so fpos sType mtime w = w & toPlaySounds %~ M.insertWith f so sound
-- where
-- sound = Sound
-- { _soundChunkID = sType
-- , _soundTime = mtime
-- , _soundStatus = SoundStatus
-- { _playStatus = ToStart
-- , _isLooping = isJust mtime
-- }
-- , _soundChannel = Nothing
-- , _soundAngDist = Just (a,0)
-- , _soundPos = fpos w
-- , _soundVolume = soundToVol sType
-- , _soundVolumeFraction = 1
-- }
-- f _ s = s {_soundTime = mtime }
-- a = soundAngle (fpos w) w
{- | Calculates the angle of a sound with reference to '_cameraViewFrom'.
Within 10 units considers the sound to be directly in front.
-}
soundAngle :: Point2 -> World -> Int16
{-# INLINE soundAngle #-}
soundAngle p w
| dist p earPos < 10 = 0
| otherwise =
round
. radToDeg
. normalizeAngle
. (+ pi)
$ argV (vNormal (p -.- earPos)) - (w ^. cWorld . camPos . camRot)
where
earPos = w ^. cWorld . camPos . camViewFrom
{- | Uses the first free origin from a list.
Does nothing if all origins are already creating sounds.
-}
soundMultiFrom ::
[SoundOrigin] ->
-- | Position
Point2 ->
-- | Sound ID
SoundID ->
-- | Frames to play for, Nothing for full length
Maybe Int ->
World ->
World
soundMultiFrom [] _ _ _ w = w
--soundMultiFrom [so] pos sType mtime w
-- = over toPlaySounds (M.insert so sound) w
-- where
-- sound = Sound
-- { _soundChunkID = sType
-- , _soundTime = mtime
-- , _soundStatus = SoundStatus
-- { _playStatus = ToStart
-- , _isLooping = isJust mtime
-- }
-- , _soundChannel = Nothing
-- , _soundAngDist = Just (a,0)
-- , _soundPos = pos
-- , _soundVolume = soundToVol sType
-- , _soundVolumeFraction = 1
-- }
-- a = soundAngle pos w
soundMultiFrom (so : sos) pos sType mtime w
| so `M.member` _playingSounds w = soundMultiFrom sos pos sType mtime w
| otherwise = over toPlaySounds (M.insert so sound) w
where
sound =
Sound
{ _soundChunkID = sType
, _soundTime = mtime
, _soundStatus =
SoundStatus
{ _playStatus = ToStart
, _isLooping = isJust mtime
}
, _soundChannel = Nothing
, _soundAngDist = Just (a, 0)
, _soundPos = pos
, _soundVolume = soundToVol sType
, _soundVolumeFraction = 1
}
a = soundAngle pos w
-- | Sets '_soundTime' to 0.
stopSoundFrom :: SoundOrigin -> World -> World
stopSoundFrom so = playingSounds . ix so . soundTime ?~ 0
--stopSoundFrom so = over (playingSounds . ix so . soundTime) (fmap $ min 0)