module Music.Time.Behavior (
Behavior,
behavior,
switch,
switch',
trimBefore,
trimAfter,
line,
sawtooth,
sine,
cosine,
unit,
impulse,
turnOn,
turnOff,
) where
import Data.AffineSpace
import Data.AffineSpace.Point
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Ratio
import Data.Semigroup
import Data.Set (Set)
import qualified Data.Set as Set
import Data.String
import Data.VectorSpace
import Prelude
import Control.Applicative
import Control.Lens hiding (Indexable, Level, above,
below, index, inside, parts,
reversed, transform, (<|), (|>))
import Data.Distributive
import Data.Functor.Rep as R
import Data.Functor.Rep.Lens
import Data.Typeable
import Music.Dynamics.Literal
import Music.Pitch.Alterable
import Music.Pitch.Augmentable
import Music.Pitch.Literal
import Music.Time.Event
import Music.Time.Internal.Transform
import Music.Time.Juxtapose
import Music.Time.Score
newtype Behavior a = Behavior { getBehavior :: Time -> a }
deriving (Functor, Applicative, Monad, Typeable)
instance Show (Behavior a) where
show _ = "<<Behavior>>"
instance Distributive Behavior where
distribute = Behavior . distribute . fmap getBehavior
instance Representable Behavior where
type Rep Behavior = Time
tabulate = Behavior
index (Behavior x) = x
instance Transformable (Behavior a) where
transform s (Behavior a) = Behavior (a `whilst` s)
where
f `whilst` s = f . transform (negateV s)
instance Reversible (Behavior a) where
rev = stretch (1)
deriving instance Semigroup a => Semigroup (Behavior a)
deriving instance Monoid a => Monoid (Behavior a)
deriving instance Num a => Num (Behavior a)
deriving instance Fractional a => Fractional (Behavior a)
deriving instance Floating a => Floating (Behavior a)
deriving instance AdditiveGroup a => AdditiveGroup (Behavior a)
instance Real a => Real (Behavior a) where
toRational = toRational . (! 0)
instance IsString a => IsString (Behavior a) where
fromString = pure . fromString
instance IsPitch a => IsPitch (Behavior a) where
fromPitch = pure . fromPitch
instance IsInterval a => IsInterval (Behavior a) where
fromInterval = pure . fromInterval
instance IsDynamics a => IsDynamics (Behavior a) where
fromDynamics = pure . fromDynamics
instance Alterable a => Alterable (Behavior a) where
sharpen = fmap sharpen
flatten = fmap flatten
instance Augmentable a => Augmentable (Behavior a) where
augment = fmap augment
diminish = fmap diminish
instance Eq a => Eq (Behavior a) where
(==) = error "No overloading for behavior: (<=)"
instance Ord a => Ord (Behavior a) where
(<=) = error "No overloading for behavior: (<=)"
(>=) = error "No overloading for behavior: (<=)"
(<) = error "No overloading for behavior: (<=)"
(>) = error "No overloading for behavior: (<=)"
max = liftA2 max
min = liftA2 min
instance Enum a => Enum (Behavior a) where
toEnum = pure . toEnum
fromEnum = fromEnum . (! 0)
instance VectorSpace a => VectorSpace (Behavior a) where
type Scalar (Behavior a) = Behavior (Scalar a)
(*^) = liftA2 (*^)
instance AffineSpace a => AffineSpace (Behavior a) where
type Diff (Behavior a) = Behavior (Diff a)
(.-.) = liftA2 (.-.)
(.+^) = liftA2 (.+^)
behavior :: Iso (Time -> a) (Time -> b) (Behavior a) (Behavior b)
behavior = R.tabulated
unbehavior :: Iso (Behavior a) (Behavior b) (Time -> a) (Time -> b)
unbehavior = from behavior
line :: Fractional a => Behavior a
line = realToFrac ^. R.tabulated
unit :: Fractional a => Behavior a
unit = switch 0 0 (switch 1 line 1)
interval :: (Fractional a, Transformable a) => Time -> Time -> Event (Behavior a)
interval t u = (t <-> u, line) ^. event
sine :: Floating a => Behavior a
sine = sin (line*tau)
cosine :: Floating a => Behavior a
cosine = cos (line*tau)
sawtooth :: RealFrac a => Behavior a
sawtooth = line fmap floor' line
impulse :: Num a => Behavior a
impulse = switch' 0 0 1 0
turnOn = switch 0 0 1
turnOff = switch 0 1 0
switch :: Time -> Behavior a -> Behavior a -> Behavior a
switch t rx ry = switch' t rx ry ry
trimBefore :: Monoid a => Time -> Behavior a -> Behavior a
trimBefore start = switch start mempty
trimAfter :: Monoid a => Time -> Behavior a -> Behavior a
trimAfter stop x = switch stop x mempty
switch' :: Time -> Behavior a -> Behavior a -> Behavior a -> Behavior a
switch' t rx ry rz = tabulate $ \u -> case u `compare` t of
LT -> rx ! u
EQ -> ry ! u
GT -> rz ! u
tau :: Floating a => a
tau = 2 * pi
floor' :: RealFrac a => a -> a
floor' = fromIntegral . floor