module Music.Score.Zip (
apply,
snapshot,
applySingle,
snapshotSingle,
) where
import Control.Monad (ap, mfilter, join, liftM, MonadPlus(..))
import Data.Semigroup
import Data.String
import Data.Foldable
import Data.Traversable
import qualified Data.List as List
import Data.VectorSpace
import Data.AffineSpace
import Data.Ratio
import Data.Ord
import Music.Score.Track
import Music.Score.Voice
import Music.Score.Score
import Music.Time
import Music.Score.Part
import Music.Score.Combinators
apply :: HasPart' a => Voice (Score a -> Score b) -> Score a -> Score b
apply x = mapAllParts (fmap $ applySingle x)
snapshot :: HasPart' a => Score b -> Score a -> Score (b, Score a)
snapshot x = mapAllParts (fmap $ snapshotSingle x)
trig :: Score a -> Score b -> Score b
trig p as = mconcat $ toList $ fmap snd $ snapshotSingle p as
applySingle :: Voice (Score a -> Score b) -> Score a -> Score b
applySingle fs as = notJoin $ fmap (\(f,s) -> f s) sampled
where
notJoin = mconcat . toList
sampled = snapshotSingle (voiceToScore fs) as
snapshotSingle :: Score a -> Score b -> Score (a, Score b)
snapshotSingle as bs = mapEventsSingle ( \t d a -> g a (onsetIn t d bs) ) as
where
g = (,)
onsetIn :: TimeT -> DurationT -> Score a -> Score a
onsetIn a b = compose . filter' (\(t,d,x) -> a <= t && t < a .+^ b) . perform
where
filter' = filterOnce
filterOnce :: (a -> Bool) -> [a] -> [a]
filterOnce p = List.takeWhile p . List.dropWhile (not . p)
before :: DurationT -> Score a -> Score a
before d = trig (return () `stretchedBy` d)
first :: Score a -> a
first = value . head . perform
where
value (a,b,c) = c
stretchedBy = flip stretch