module Music.Time.Position (
module Music.Time.Duration,
HasPosition(..),
position,
era,
onset,
midpoint,
offset,
preOnset,
postOffset,
postOnset,
startAt,
stopAt,
placeAt,
stretchRelative,
stretchRelativeOnset,
stretchRelativeMidpoint,
stretchRelativeOffset,
delayRelative,
delayRelativeOnset,
delayRelativeMidpoint,
delayRelativeOffset,
transformRelative,
transformRelativeOnset,
transformRelativeMidpoint,
transformRelativeOffset,
) where
import Control.Lens hiding (Indexable, Level, above,
below, index, inside, parts,
reversed, transform, (<|), (|>))
import Data.AffineSpace
import Data.AffineSpace.Point
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Semigroup
import Data.Set (Set)
import qualified Data.Set as Set
import Data.VectorSpace hiding (Sum)
import Music.Time.Duration
import Music.Time.Internal.Util
class HasDuration a => HasPosition a where
_position :: a -> Duration -> Time
_position x = alerp a b where (a, b) = (_era x)^.onsetAndOffset
_era :: HasPosition a => a -> Span
_era x = x `_position` 0 <-> x `_position` 1
instance HasPosition Span where
_era = id
#ifndef GHCI
instance (HasPosition a, Transformable a) => HasDuration [a] where
_duration x = _offset x .-. _onset x
instance (HasPosition a, Transformable a) => HasPosition [a] where
_era x = (f x, g x)^.from onsetAndOffset
where
f = foldr min 0 . fmap _onset
g = foldr max 0 . fmap _offset
#endif
#line 123
position :: (HasPosition a, Transformable a) => Duration -> Lens' a Time
position d = lens (`_position` d) (flip $ placeAt d)
onset :: (HasPosition a, Transformable a) => Lens' a Time
onset = position 0
offset :: (HasPosition a, Transformable a) => Lens' a Time
offset = position 1
preOnset :: (HasPosition a, Transformable a) => Lens' a Time
preOnset = position (0.5)
midpoint :: (HasPosition a, Transformable a) => Lens' a Time
midpoint = position 0.5
postOnset :: (HasPosition a, Transformable a) => Lens' a Time
postOnset = position 0.5
postOffset :: (HasPosition a, Transformable a) => Lens' a Time
postOffset = position 1.5
startAt :: (Transformable a, HasPosition a) => Time -> a -> a
startAt t x = (t .-. x^.onset) `delay` x
stopAt :: (Transformable a, HasPosition a) => Time -> a -> a
stopAt t x = (t .-. x^.offset) `delay` x
placeAt :: (Transformable a, HasPosition a) => Duration -> Time -> a -> a
placeAt p t x = (t .-. x `_position` p) `delay` x
_onset, _offset :: (HasPosition a, Transformable a) => a -> Time
_onset = (`_position` 0)
_offset = (`_position` 1.0)
_setEra :: (HasPosition a, Transformable a) => Span -> a -> a
_setEra s x = transform (s ^-^ view era x) x
era :: (HasPosition a, Transformable a) => Lens' a Span
era = lens _era (flip _setEra)
stretchRelative :: (HasPosition a, Transformable a) => Duration -> Duration -> a -> a
stretchRelative p n x = over (transformed $ undelaying (realToFrac $ x^.position p)) (stretch n) x
stretchRelativeOnset :: (HasPosition a, Transformable a) => Duration -> a -> a
stretchRelativeOnset = stretchRelative 0
stretchRelativeMidpoint :: (HasPosition a, Transformable a) => Duration -> a -> a
stretchRelativeMidpoint = stretchRelative 0.5
stretchRelativeOffset :: (HasPosition a, Transformable a) => Duration -> a -> a
stretchRelativeOffset = stretchRelative 1
delayRelative :: (HasPosition a, Transformable a) => Duration -> Duration -> a -> a
delayRelative p n x = over (transformed $ undelaying (realToFrac $ x^.position p)) (delay n) x
delayRelativeOnset :: (HasPosition a, Transformable a) => Duration -> a -> a
delayRelativeOnset = delayRelative 0
delayRelativeMidpoint :: (HasPosition a, Transformable a) => Duration -> a -> a
delayRelativeMidpoint = delayRelative 0.5
delayRelativeOffset :: (HasPosition a, Transformable a) => Duration -> a -> a
delayRelativeOffset = delayRelative 1
transformRelative :: (HasPosition a, Transformable a) => Duration -> Span -> a -> a
transformRelative p n x = over (transformed $ undelaying (realToFrac $ x^.position p)) (transform n) x
transformRelativeOnset :: (HasPosition a, Transformable a) => Span -> a -> a
transformRelativeOnset = transformRelative 0
transformRelativeMidpoint :: (HasPosition a, Transformable a) => Span -> a -> a
transformRelativeMidpoint = transformRelative 0.5
transformRelativeOffset :: (HasPosition a, Transformable a) => Span -> a -> a
transformRelativeOffset = transformRelative 1