packages feed

music-score 1.7.2 → 1.8

raw patch · 63 files changed

+2026/−2361 lines, 63 filesdep +transformers-compatdep −semigroupoidsdep ~lensdep ~lilyponddep ~music-dynamics-literalPVP ok

version bump matches the API change (PVP)

Dependencies added: transformers-compat

Dependencies removed: semigroupoids

Dependency ranges changed: lens, lilypond, music-dynamics-literal, music-pitch-literal, musicxml2

API changes (from Hackage documentation)

- Music.Score.Articulation: instance HasArticulation a b => HasArticulation (Delayed a) (Delayed b)
- Music.Score.Articulation: instance HasArticulation a b => HasArticulation (Stretched a) (Stretched b)
- Music.Score.Articulation: instance HasArticulations a b => HasArticulations (Chord a) (Chord b)
- Music.Score.Articulation: instance HasArticulations a b => HasArticulations (Delayed a) (Delayed b)
- Music.Score.Articulation: instance HasArticulations a b => HasArticulations (Stretched a) (Stretched b)
- Music.Score.Dynamics: instance HasDynamic a b => HasDynamic (Delayed a) (Delayed b)
- Music.Score.Dynamics: instance HasDynamic a b => HasDynamic (Stretched a) (Stretched b)
- Music.Score.Dynamics: instance HasDynamics a b => HasDynamics (Chord a) (Chord b)
- Music.Score.Dynamics: instance HasDynamics a b => HasDynamics (Delayed a) (Delayed b)
- Music.Score.Dynamics: instance HasDynamics a b => HasDynamics (Stretched a) (Stretched b)
- Music.Score.Instances: instance (Enum v, Bounded a) => Bounded (PartT v a)
- Music.Score.Instances: instance (Enum v, Enum a) => Enum (PartT v a)
- Music.Score.Instances: instance (Enum v, Eq v, Num a) => Num (PartT v a)
- Music.Score.Instances: instance (Enum v, Ord v, Num a, Ord a, Real a) => Real (PartT v a)
- Music.Score.Instances: instance (Enum v, Ord v, Real a, Enum a, Integral a) => Integral (PartT v a)
- Music.Score.Instances: instance (Transformable a, Transformable b, Transformable c) => Transformable (a, b, c)
- Music.Score.Instances: instance Alterable a => Alterable (ArticulationT n a)
- Music.Score.Instances: instance Alterable a => Alterable (ColorT a)
- Music.Score.Instances: instance Alterable a => Alterable (DynamicT n a)
- Music.Score.Instances: instance Alterable a => Alterable (HarmonicT a)
- Music.Score.Instances: instance Alterable a => Alterable (PartT n a)
- Music.Score.Instances: instance Alterable a => Alterable (Score a)
- Music.Score.Instances: instance Alterable a => Alterable (SlideT a)
- Music.Score.Instances: instance Alterable a => Alterable (TextT a)
- Music.Score.Instances: instance Alterable a => Alterable (TieT a)
- Music.Score.Instances: instance Augmentable a => Augmentable (ArticulationT n a)
- Music.Score.Instances: instance Augmentable a => Augmentable (ColorT a)
- Music.Score.Instances: instance Augmentable a => Augmentable (DynamicT n a)
- Music.Score.Instances: instance Augmentable a => Augmentable (HarmonicT a)
- Music.Score.Instances: instance Augmentable a => Augmentable (PartT n a)
- Music.Score.Instances: instance Augmentable a => Augmentable (Score a)
- Music.Score.Instances: instance Augmentable a => Augmentable (SlideT a)
- Music.Score.Instances: instance Augmentable a => Augmentable (TextT a)
- Music.Score.Instances: instance Augmentable a => Augmentable (TieT a)
- Music.Score.Instances: instance Bounded a => Bounded [a]
- Music.Score.Instances: instance Enum a => Enum [a]
- Music.Score.Instances: instance HasArticulation a b => HasArticulation (ColorT a) (ColorT b)
- Music.Score.Instances: instance HasArticulation a b => HasArticulation (PartT p a) (PartT p b)
- Music.Score.Instances: instance HasArticulations a b => HasArticulations (ColorT a) (ColorT b)
- Music.Score.Instances: instance HasArticulations a b => HasArticulations (PartT p a) (PartT p b)
- Music.Score.Instances: instance HasDynamic a b => HasDynamic (ArticulationT p a) (ArticulationT p b)
- Music.Score.Instances: instance HasDynamic a b => HasDynamic (ColorT a) (ColorT b)
- Music.Score.Instances: instance HasDynamic a b => HasDynamic (PartT p a) (PartT p b)
- Music.Score.Instances: instance HasDynamics a b => HasDynamics (ArticulationT p a) (ArticulationT p b)
- Music.Score.Instances: instance HasDynamics a b => HasDynamics (ColorT a) (ColorT b)
- Music.Score.Instances: instance HasDynamics a b => HasDynamics (PartT p a) (PartT p b)
- Music.Score.Instances: instance HasHarmonic a => HasHarmonic (ColorT a)
- Music.Score.Instances: instance HasHarmonic a => HasHarmonic (PartT n a)
- Music.Score.Instances: instance HasHarmonic a => HasHarmonic (SlideT a)
- Music.Score.Instances: instance HasHarmonic a => HasHarmonic (TextT a)
- Music.Score.Instances: instance HasHarmonic a => HasHarmonic (TieT a)
- Music.Score.Instances: instance HasPitch a b => HasPitch (ArticulationT p a) (ArticulationT p b)
- Music.Score.Instances: instance HasPitch a b => HasPitch (ColorT a) (ColorT b)
- Music.Score.Instances: instance HasPitch a b => HasPitch (DynamicT p a) (DynamicT p b)
- Music.Score.Instances: instance HasPitch a b => HasPitch (PartT p a) (PartT p b)
- Music.Score.Instances: instance HasPitches a b => HasPitches (ArticulationT p a) (ArticulationT p b)
- Music.Score.Instances: instance HasPitches a b => HasPitches (ColorT a) (ColorT b)
- Music.Score.Instances: instance HasPitches a b => HasPitches (DynamicT p a) (DynamicT p b)
- Music.Score.Instances: instance HasPitches a b => HasPitches (PartT p a) (PartT p b)
- Music.Score.Instances: instance HasSlide a => HasSlide (ColorT a)
- Music.Score.Instances: instance HasSlide a => HasSlide (HarmonicT a)
- Music.Score.Instances: instance HasSlide a => HasSlide (PartT n a)
- Music.Score.Instances: instance HasSlide a => HasSlide (TextT a)
- Music.Score.Instances: instance HasSlide a => HasSlide (TieT a)
- Music.Score.Instances: instance HasText a => HasText (ColorT a)
- Music.Score.Instances: instance HasText a => HasText (HarmonicT a)
- Music.Score.Instances: instance HasText a => HasText (PartT n a)
- Music.Score.Instances: instance HasText a => HasText (SlideT a)
- Music.Score.Instances: instance HasText a => HasText (TieT a)
- Music.Score.Instances: instance HasTremolo a => HasTremolo (ColorT a)
- Music.Score.Instances: instance HasTremolo a => HasTremolo (HarmonicT a)
- Music.Score.Instances: instance HasTremolo a => HasTremolo (PartT n a)
- Music.Score.Instances: instance HasTremolo a => HasTremolo (SlideT a)
- Music.Score.Instances: instance HasTremolo a => HasTremolo (TextT a)
- Music.Score.Instances: instance HasTremolo a => HasTremolo (TieT a)
- Music.Score.Instances: instance IsDynamics a => IsDynamics (Average a)
- Music.Score.Instances: instance IsDynamics a => IsDynamics (ColorT a)
- Music.Score.Instances: instance IsDynamics a => IsDynamics (HarmonicT a)
- Music.Score.Instances: instance IsDynamics a => IsDynamics (SlideT a)
- Music.Score.Instances: instance IsDynamics a => IsDynamics (TextT a)
- Music.Score.Instances: instance IsInterval a => IsInterval (Average a)
- Music.Score.Instances: instance IsPitch a => IsPitch (Average a)
- Music.Score.Instances: instance IsPitch a => IsPitch (ColorT a)
- Music.Score.Instances: instance IsPitch a => IsPitch (HarmonicT a)
- Music.Score.Instances: instance IsPitch a => IsPitch (SlideT a)
- Music.Score.Instances: instance IsPitch a => IsPitch (TextT a)
- Music.Score.Instances: instance Reversible a => Reversible (ColorT a)
- Music.Score.Instances: instance Reversible a => Reversible (HarmonicT a)
- Music.Score.Instances: instance Reversible a => Reversible (SlideT a)
- Music.Score.Instances: instance Reversible a => Reversible (TextT a)
- Music.Score.Instances: instance Semigroup a => Semigroup (HarmonicT a)
- Music.Score.Instances: instance Semigroup a => Semigroup (PartT n a)
- Music.Score.Instances: instance Semigroup a => Semigroup (SlideT a)
- Music.Score.Instances: instance Semigroup a => Semigroup (TextT a)
- Music.Score.Instances: instance Semigroup a => Semigroup (TieT a)
- Music.Score.Instances: instance Tiable a => Tiable (HarmonicT a)
- Music.Score.Instances: instance Tiable a => Tiable (Score a)
- Music.Score.Instances: instance Tiable a => Tiable (SlideT a)
- Music.Score.Instances: instance Tiable a => Tiable (TextT a)
- Music.Score.Instances: instance Transformable a => Transformable (Average a)
- Music.Score.Instances: instance Transformable a => Transformable (ColorT a)
- Music.Score.Instances: instance Transformable a => Transformable (Ctxt a)
- Music.Score.Instances: instance Transformable a => Transformable (HarmonicT a)
- Music.Score.Instances: instance Transformable a => Transformable (Maybe a)
- Music.Score.Instances: instance Transformable a => Transformable (SlideT a)
- Music.Score.Instances: instance Transformable a => Transformable (TextT a)
- Music.Score.Meta: (</>) :: (HasParts' a, Enum (Part a)) => Score a -> Score a -> Score a
- Music.Score.Meta: rcat :: (HasParts' a, Enum (Part a)) => [Score a] -> Score a
- Music.Score.Part: instance HasPart a b => HasPart (Note a) (Note b)
- Music.Score.Part: instance HasParts a b => HasParts (Note a) (Note b)
- Music.Score.Pitch: instance HasPitch a b => HasPitch (Delayed a) (Delayed b)
- Music.Score.Pitch: instance HasPitch a b => HasPitch (Stretched a) (Stretched b)
- Music.Score.Pitch: instance HasPitches a b => HasPitches (Chord a) (Chord b)
- Music.Score.Pitch: instance HasPitches a b => HasPitches (Delayed a) (Delayed b)
- Music.Score.Pitch: instance HasPitches a b => HasPitches (Stretched a) (Stretched b)
- Music.Score.Slide: instance HasSlide a => HasSlide (Stretched a)
- Music.Score.Text: instance HasText a => HasText (Stretched a)
- Music.Score.Ties: splitTiesVoiceAt :: Tiable a => [Duration] -> Voice a -> [Voice a]
- Music.Time.Chord: chord :: Getter [Delayed a] (Chord a)
- Music.Time.Chord: data Chord a
- Music.Time.Chord: instance HasDuration (Chord a)
- Music.Time.Chord: instance Reversible a => Reversible (Chord a)
- Music.Time.Chord: instance Splittable a => Splittable (Chord a)
- Music.Time.Chord: instance Transformable (Chord a)
- Music.Time.Chord: unchord :: Lens (Chord a) (Chord b) [Delayed a] [Delayed b]
- Music.Time.Chord: unsafeChord :: Iso (Chord a) (Chord b) [Delayed a] [Delayed b]
- Music.Time.Delayed: data Delayed a
- Music.Time.Delayed: delayed :: Iso (Time, a) (Time, b) (Delayed a) (Delayed b)
- Music.Time.Delayed: delayedValue :: (Transformable a, Transformable b) => Lens (Delayed a) (Delayed b) a b
- Music.Time.Delayed: instance (Show a, Transformable a) => Show (Delayed a)
- Music.Time.Delayed: instance Applicative Delayed
- Music.Time.Delayed: instance Eq a => Eq (Delayed a)
- Music.Time.Delayed: instance Foldable Delayed
- Music.Time.Delayed: instance Functor Delayed
- Music.Time.Delayed: instance HasDuration (Delayed a)
- Music.Time.Delayed: instance HasPosition (Delayed a)
- Music.Time.Delayed: instance IsDynamics a => IsDynamics (Delayed a)
- Music.Time.Delayed: instance IsInterval a => IsInterval (Delayed a)
- Music.Time.Delayed: instance IsPitch a => IsPitch (Delayed a)
- Music.Time.Delayed: instance IsString a => IsString (Delayed a)
- Music.Time.Delayed: instance Monad Delayed
- Music.Time.Delayed: instance Reversible (Delayed a)
- Music.Time.Delayed: instance Rewrapped (Delayed a) (Delayed b)
- Music.Time.Delayed: instance Splittable a => Splittable (Delayed a)
- Music.Time.Delayed: instance Transformable (Delayed a)
- Music.Time.Delayed: instance Traversable Delayed
- Music.Time.Delayed: instance Typeable Delayed
- Music.Time.Delayed: instance Wrapped (Delayed a)
- Music.Time.Duration: instance HasDuration Time
- Music.Time.Internal.Convert: voiceToScore :: Voice a -> Score a
- Music.Time.Internal.Convert: voiceToScore' :: Voice (Maybe a) -> Score a
- Music.Time.Internal.Transform: itransform :: Transformable a => Span -> a -> a
- Music.Time.Internal.Transform: itransformed :: (Transformable a, Transformable b) => Span -> Iso a b a b
- Music.Time.Internal.Transform: spanned :: (Transformable b, Transformable a, Profunctor p, Functor f) => Span -> p a (f b) -> p a (f b)
- Music.Time.Note: event :: Iso (Note a) (Note b) (Time, Duration, a) (Time, Duration, b)
- Music.Time.Note: instance Comonad Note
- Music.Time.Note: instance HasPosition (Note a)
- Music.Time.Note: instance Reversible (Note a)
- Music.Time.Note: instance Splittable a => Splittable (Note a)
- Music.Time.Note: noteValue :: (Transformable a, Transformable b) => Lens (Note a) (Note b) a b
- Music.Time.Past: instance HasDuration (Future a)
- Music.Time.Past: instance HasDuration (Past a)
- Music.Time.Past: instance HasPosition (Future a)
- Music.Time.Past: instance HasPosition (Past a)
- Music.Time.Position: _getEra :: HasPosition a => a -> Span
- Music.Time.Position: _onset, _offset :: HasPosition a => a -> Time
- Music.Time.Position: _setEra :: (HasPosition a, Transformable a) => Span -> a -> a
- Music.Time.Position: instance HasPosition Time
- Music.Time.Score: filterEvents :: (Time -> Duration -> a -> Bool) -> Score a -> Score a
- Music.Time.Score: instance (Show a, Transformable a) => Show (NScore a)
- Music.Time.Score: instance Alternative NScore
- Music.Time.Score: instance Applicative NScore
- Music.Time.Score: instance Eq a => Eq (NScore a)
- Music.Time.Score: instance Foldable NScore
- Music.Time.Score: instance Functor NScore
- Music.Time.Score: instance HasDuration (NScore a)
- Music.Time.Score: instance HasPosition (NScore a)
- Music.Time.Score: instance Monad NScore
- Music.Time.Score: instance MonadPlus NScore
- Music.Time.Score: instance Monoid (NScore a)
- Music.Time.Score: instance Reversible a => Reversible (NScore a)
- Music.Time.Score: instance Reversible a => Reversible (Score a)
- Music.Time.Score: instance Rewrapped (NScore a) (NScore b)
- Music.Time.Score: instance Semigroup (NScore a)
- Music.Time.Score: instance Splittable a => Splittable (NScore a)
- Music.Time.Score: instance Splittable a => Splittable (Score a)
- Music.Time.Score: instance Transformable (NScore a)
- Music.Time.Score: instance Traversable NScore
- Music.Time.Score: instance Typeable NScore
- Music.Time.Score: instance Wrapped (NScore a)
- Music.Time.Score: mapEvents :: (Time -> Duration -> a -> b) -> Score a -> Score b
- Music.Time.Score: mapFilterEvents :: (Time -> Duration -> a -> Maybe b) -> Score a -> Score b
- Music.Time.Score: notes :: Lens (Score a) (Score b) [Note a] [Note b]
- Music.Time.Score: simult :: Transformable a => Lens (Score a) (Score b) (Score [a]) (Score [b])
- Music.Time.Score: singleNote :: Prism' (Score a) (Note a)
- Music.Time.Score: unsafeNotes :: Iso (Score a) (Score b) [Note a] [Note b]
- Music.Time.Stretched: data Stretched a
- Music.Time.Stretched: instance (Show a, Transformable a) => Show (Stretched a)
- Music.Time.Stretched: instance Applicative Stretched
- Music.Time.Stretched: instance Eq a => Eq (Stretched a)
- Music.Time.Stretched: instance Floating a => Floating (Stretched a)
- Music.Time.Stretched: instance Foldable Stretched
- Music.Time.Stretched: instance Fractional a => Fractional (Stretched a)
- Music.Time.Stretched: instance Functor Stretched
- Music.Time.Stretched: instance HasDuration (Stretched a)
- Music.Time.Stretched: instance IsDynamics a => IsDynamics (Stretched a)
- Music.Time.Stretched: instance IsInterval a => IsInterval (Stretched a)
- Music.Time.Stretched: instance IsPitch a => IsPitch (Stretched a)
- Music.Time.Stretched: instance IsString a => IsString (Stretched a)
- Music.Time.Stretched: instance Monad Stretched
- Music.Time.Stretched: instance Num a => Num (Stretched a)
- Music.Time.Stretched: instance Ord a => Ord (Stretched a)
- Music.Time.Stretched: instance Real a => Real (Stretched a)
- Music.Time.Stretched: instance RealFrac a => RealFrac (Stretched a)
- Music.Time.Stretched: instance Reversible (Stretched a)
- Music.Time.Stretched: instance Rewrapped (Stretched a) (Stretched b)
- Music.Time.Stretched: instance Splittable a => Splittable (Stretched a)
- Music.Time.Stretched: instance Transformable (Stretched a)
- Music.Time.Stretched: instance Traversable Stretched
- Music.Time.Stretched: instance Typeable Stretched
- Music.Time.Stretched: instance Wrapped (Stretched a)
- Music.Time.Stretched: stretched :: Iso (Duration, a) (Duration, b) (Stretched a) (Stretched b)
- Music.Time.Stretched: stretchedValue :: (Transformable a, Transformable b) => Lens (Stretched a) (Stretched b) a b
- Music.Time.Track: delayeds :: Lens (Track a) (Track b) [Delayed a] [Delayed b]
- Music.Time.Track: instance HasDuration (Track a)
- Music.Time.Track: instance HasPosition (Track a)
- Music.Time.Track: instance Reversible a => Reversible (Track a)
- Music.Time.Track: instance Splittable a => Splittable (Track a)
- Music.Time.Track: instance Transformable (Track a)
- Music.Time.Track: singleDelayed :: Prism' (Track a) (Delayed a)
- Music.Time.Transform: conjugateS :: Span -> Span -> Span
- Music.Time.Transform: delayTime :: Transformable a => Time -> a -> a
- Music.Time.Transform: itransform :: Transformable a => Span -> a -> a
- Music.Time.Transform: onSpan :: (Transformable s, Transformable t, Functor f) => LensLike f s t a b -> Span -> LensLike f s t a b
- Music.Time.Transform: spanned :: (Transformable b, Transformable a, Profunctor p, Functor f) => Span -> p a (f b) -> p a (f b)
- Music.Time.Transform: whilst :: (Transformable a, Transformable b) => (a -> b) -> Span -> a -> b
- Music.Time.Types: fromDuration :: Fractional a => Duration -> a
- Music.Time.Types: fromTime :: Fractional a => Time -> a
- Music.Time.Types: isProper :: Span -> Bool
- Music.Time.Types: toDuration :: Real a => a -> Duration
- Music.Time.Types: toTime :: Real a => a -> Time
- Music.Time.Voice: eventsV :: Lens (Voice a) (Voice b) [(Duration, a)] [(Duration, b)]
- Music.Time.Voice: instance Cons (Voice a) (Voice b) (Stretched a) (Stretched b)
- Music.Time.Voice: instance Snoc (Voice a) (Voice b) (Stretched a) (Stretched b)
- Music.Time.Voice: instance Splittable a => Splittable (Voice a)
- Music.Time.Voice: listAsVoice :: Iso [a] [b] (Voice a) (Voice b)
- Music.Time.Voice: reverseDurations :: Voice a -> Voice a
- Music.Time.Voice: reverseValues :: Voice a -> Voice a
- Music.Time.Voice: rotateDurations :: Int -> Voice a -> Voice a
- Music.Time.Voice: rotateValues :: Int -> Voice a -> Voice a
- Music.Time.Voice: singleStretched :: Prism' (Voice a) (Stretched a)
- Music.Time.Voice: stretcheds :: Lens (Voice a) (Voice b) [Stretched a] [Stretched b]
- Music.Time.Voice: unsafeEventsV :: Iso (Voice a) (Voice b) [(Duration, a)] [(Duration, b)]
- Music.Time.Voice: unsafeStretcheds :: Iso (Voice a) (Voice b) [Stretched a] [Stretched b]
- Music.Time.Voice: voiceAsList :: Iso (Voice a) (Voice b) [a] [b]
- Music.Time.Voice: voiceLens :: (s -> a) -> (b -> s -> t) -> Lens (Voice s) (Voice t) (Voice a) (Voice b)
- Music.Time.Voice: withDurations :: ([Duration] -> [Duration]) -> Voice a -> Voice a
- Music.Time.Voice: withValues :: ([a] -> [b]) -> Voice a -> Voice b
+ Data.Functor.Context: addCtxt :: [a] -> [Ctxt a]
+ Data.Functor.Context: instance Eq a => Eq (Ctxt a)
+ Data.Functor.Context: instance Ord a => Ord (Ctxt a)
+ Data.Functor.Context: instance Show a => Show (Ctxt a)
+ Data.Functor.Context: toCtxt :: (Maybe a, a, Maybe a) -> Ctxt a
+ Music.Score.Articulation: instance HasArticulation a b => HasArticulation (Event a) (Event b)
+ Music.Score.Articulation: instance HasArticulation a b => HasArticulation (Placed a) (Placed b)
+ Music.Score.Articulation: instance HasArticulations a b => HasArticulations (Event a) (Event b)
+ Music.Score.Articulation: instance HasArticulations a b => HasArticulations (Placed a) (Placed b)
+ Music.Score.Dynamics: instance HasDynamic a b => HasDynamic (Event a) (Event b)
+ Music.Score.Dynamics: instance HasDynamic a b => HasDynamic (Placed a) (Placed b)
+ Music.Score.Dynamics: instance HasDynamics a b => HasDynamics (Event a) (Event b)
+ Music.Score.Dynamics: instance HasDynamics a b => HasDynamics (Placed a) (Placed b)
+ Music.Score.Internal.Instances: instance (Enum v, Bounded a) => Bounded (PartT v a)
+ Music.Score.Internal.Instances: instance (Enum v, Enum a) => Enum (PartT v a)
+ Music.Score.Internal.Instances: instance (Enum v, Eq v, Num a) => Num (PartT v a)
+ Music.Score.Internal.Instances: instance (Enum v, Ord v, Num a, Ord a, Real a) => Real (PartT v a)
+ Music.Score.Internal.Instances: instance (Enum v, Ord v, Real a, Enum a, Integral a) => Integral (PartT v a)
+ Music.Score.Internal.Instances: instance (Transformable a, Transformable b, Transformable c) => Transformable (a, b, c)
+ Music.Score.Internal.Instances: instance Alterable a => Alterable (ArticulationT n a)
+ Music.Score.Internal.Instances: instance Alterable a => Alterable (ColorT a)
+ Music.Score.Internal.Instances: instance Alterable a => Alterable (DynamicT n a)
+ Music.Score.Internal.Instances: instance Alterable a => Alterable (HarmonicT a)
+ Music.Score.Internal.Instances: instance Alterable a => Alterable (PartT n a)
+ Music.Score.Internal.Instances: instance Alterable a => Alterable (Score a)
+ Music.Score.Internal.Instances: instance Alterable a => Alterable (SlideT a)
+ Music.Score.Internal.Instances: instance Alterable a => Alterable (TextT a)
+ Music.Score.Internal.Instances: instance Alterable a => Alterable (TieT a)
+ Music.Score.Internal.Instances: instance Augmentable a => Augmentable (ArticulationT n a)
+ Music.Score.Internal.Instances: instance Augmentable a => Augmentable (ColorT a)
+ Music.Score.Internal.Instances: instance Augmentable a => Augmentable (DynamicT n a)
+ Music.Score.Internal.Instances: instance Augmentable a => Augmentable (HarmonicT a)
+ Music.Score.Internal.Instances: instance Augmentable a => Augmentable (PartT n a)
+ Music.Score.Internal.Instances: instance Augmentable a => Augmentable (Score a)
+ Music.Score.Internal.Instances: instance Augmentable a => Augmentable (SlideT a)
+ Music.Score.Internal.Instances: instance Augmentable a => Augmentable (TextT a)
+ Music.Score.Internal.Instances: instance Augmentable a => Augmentable (TieT a)
+ Music.Score.Internal.Instances: instance Bounded a => Bounded [a]
+ Music.Score.Internal.Instances: instance Enum a => Enum [a]
+ Music.Score.Internal.Instances: instance HasArticulation a b => HasArticulation (ColorT a) (ColorT b)
+ Music.Score.Internal.Instances: instance HasArticulation a b => HasArticulation (PartT p a) (PartT p b)
+ Music.Score.Internal.Instances: instance HasArticulations a b => HasArticulations (ColorT a) (ColorT b)
+ Music.Score.Internal.Instances: instance HasArticulations a b => HasArticulations (PartT p a) (PartT p b)
+ Music.Score.Internal.Instances: instance HasDynamic a b => HasDynamic (ArticulationT p a) (ArticulationT p b)
+ Music.Score.Internal.Instances: instance HasDynamic a b => HasDynamic (ColorT a) (ColorT b)
+ Music.Score.Internal.Instances: instance HasDynamic a b => HasDynamic (PartT p a) (PartT p b)
+ Music.Score.Internal.Instances: instance HasDynamics a b => HasDynamics (ArticulationT p a) (ArticulationT p b)
+ Music.Score.Internal.Instances: instance HasDynamics a b => HasDynamics (ColorT a) (ColorT b)
+ Music.Score.Internal.Instances: instance HasDynamics a b => HasDynamics (PartT p a) (PartT p b)
+ Music.Score.Internal.Instances: instance HasHarmonic a => HasHarmonic (ColorT a)
+ Music.Score.Internal.Instances: instance HasHarmonic a => HasHarmonic (PartT n a)
+ Music.Score.Internal.Instances: instance HasHarmonic a => HasHarmonic (SlideT a)
+ Music.Score.Internal.Instances: instance HasHarmonic a => HasHarmonic (TextT a)
+ Music.Score.Internal.Instances: instance HasHarmonic a => HasHarmonic (TieT a)
+ Music.Score.Internal.Instances: instance HasPitch a b => HasPitch (ArticulationT p a) (ArticulationT p b)
+ Music.Score.Internal.Instances: instance HasPitch a b => HasPitch (ColorT a) (ColorT b)
+ Music.Score.Internal.Instances: instance HasPitch a b => HasPitch (DynamicT p a) (DynamicT p b)
+ Music.Score.Internal.Instances: instance HasPitch a b => HasPitch (PartT p a) (PartT p b)
+ Music.Score.Internal.Instances: instance HasPitches a b => HasPitches (ArticulationT p a) (ArticulationT p b)
+ Music.Score.Internal.Instances: instance HasPitches a b => HasPitches (ColorT a) (ColorT b)
+ Music.Score.Internal.Instances: instance HasPitches a b => HasPitches (DynamicT p a) (DynamicT p b)
+ Music.Score.Internal.Instances: instance HasPitches a b => HasPitches (PartT p a) (PartT p b)
+ Music.Score.Internal.Instances: instance HasSlide a => HasSlide (ColorT a)
+ Music.Score.Internal.Instances: instance HasSlide a => HasSlide (HarmonicT a)
+ Music.Score.Internal.Instances: instance HasSlide a => HasSlide (PartT n a)
+ Music.Score.Internal.Instances: instance HasSlide a => HasSlide (TextT a)
+ Music.Score.Internal.Instances: instance HasSlide a => HasSlide (TieT a)
+ Music.Score.Internal.Instances: instance HasText a => HasText (ColorT a)
+ Music.Score.Internal.Instances: instance HasText a => HasText (HarmonicT a)
+ Music.Score.Internal.Instances: instance HasText a => HasText (PartT n a)
+ Music.Score.Internal.Instances: instance HasText a => HasText (SlideT a)
+ Music.Score.Internal.Instances: instance HasText a => HasText (TieT a)
+ Music.Score.Internal.Instances: instance HasTremolo a => HasTremolo (ColorT a)
+ Music.Score.Internal.Instances: instance HasTremolo a => HasTremolo (HarmonicT a)
+ Music.Score.Internal.Instances: instance HasTremolo a => HasTremolo (PartT n a)
+ Music.Score.Internal.Instances: instance HasTremolo a => HasTremolo (SlideT a)
+ Music.Score.Internal.Instances: instance HasTremolo a => HasTremolo (TextT a)
+ Music.Score.Internal.Instances: instance HasTremolo a => HasTremolo (TieT a)
+ Music.Score.Internal.Instances: instance IsDynamics a => IsDynamics (Average a)
+ Music.Score.Internal.Instances: instance IsDynamics a => IsDynamics (ColorT a)
+ Music.Score.Internal.Instances: instance IsDynamics a => IsDynamics (HarmonicT a)
+ Music.Score.Internal.Instances: instance IsDynamics a => IsDynamics (SlideT a)
+ Music.Score.Internal.Instances: instance IsDynamics a => IsDynamics (TextT a)
+ Music.Score.Internal.Instances: instance IsInterval a => IsInterval (Average a)
+ Music.Score.Internal.Instances: instance IsPitch a => IsPitch (Average a)
+ Music.Score.Internal.Instances: instance IsPitch a => IsPitch (ColorT a)
+ Music.Score.Internal.Instances: instance IsPitch a => IsPitch (HarmonicT a)
+ Music.Score.Internal.Instances: instance IsPitch a => IsPitch (SlideT a)
+ Music.Score.Internal.Instances: instance IsPitch a => IsPitch (TextT a)
+ Music.Score.Internal.Instances: instance Reversible a => Reversible (ColorT a)
+ Music.Score.Internal.Instances: instance Reversible a => Reversible (HarmonicT a)
+ Music.Score.Internal.Instances: instance Reversible a => Reversible (SlideT a)
+ Music.Score.Internal.Instances: instance Reversible a => Reversible (TextT a)
+ Music.Score.Internal.Instances: instance Semigroup a => Semigroup (HarmonicT a)
+ Music.Score.Internal.Instances: instance Semigroup a => Semigroup (PartT n a)
+ Music.Score.Internal.Instances: instance Semigroup a => Semigroup (SlideT a)
+ Music.Score.Internal.Instances: instance Semigroup a => Semigroup (TextT a)
+ Music.Score.Internal.Instances: instance Semigroup a => Semigroup (TieT a)
+ Music.Score.Internal.Instances: instance Tiable a => Tiable (HarmonicT a)
+ Music.Score.Internal.Instances: instance Tiable a => Tiable (Score a)
+ Music.Score.Internal.Instances: instance Tiable a => Tiable (SlideT a)
+ Music.Score.Internal.Instances: instance Tiable a => Tiable (TextT a)
+ Music.Score.Internal.Instances: instance Transformable a => Transformable (Average a)
+ Music.Score.Internal.Instances: instance Transformable a => Transformable (ColorT a)
+ Music.Score.Internal.Instances: instance Transformable a => Transformable (Ctxt a)
+ Music.Score.Internal.Instances: instance Transformable a => Transformable (HarmonicT a)
+ Music.Score.Internal.Instances: instance Transformable a => Transformable (Maybe a)
+ Music.Score.Internal.Instances: instance Transformable a => Transformable (SlideT a)
+ Music.Score.Internal.Instances: instance Transformable a => Transformable (TextT a)
+ Music.Score.Meta.Clef: instance IsPitch Clef
+ Music.Score.Part: (</>) :: (HasParts' a, Enum (Part a)) => Score a -> Score a -> Score a
+ Music.Score.Part: instance HasPart a b => HasPart (Event a) (Event b)
+ Music.Score.Part: instance HasParts a b => HasParts (Event a) (Event b)
+ Music.Score.Part: rcat :: (HasParts' a, Enum (Part a)) => [Score a] -> Score a
+ Music.Score.Pitch: instance HasPitch a b => HasPitch (Event a) (Event b)
+ Music.Score.Pitch: instance HasPitch a b => HasPitch (Placed a) (Placed b)
+ Music.Score.Pitch: instance HasPitches a b => HasPitches (Event a) (Event b)
+ Music.Score.Pitch: instance HasPitches a b => HasPitches (Map k a) (Map k b)
+ Music.Score.Pitch: instance HasPitches a b => HasPitches (Placed a) (Placed b)
+ Music.Score.Pitch: instance HasPitches a b => HasPitches (Seq a) (Seq b)
+ Music.Score.Slide: instance HasSlide a => HasSlide (Note a)
+ Music.Score.Text: instance HasText a => HasText (Note a)
+ Music.Score.Ties: isTieBeginning :: Tiable a => a -> Bool
+ Music.Score.Ties: isTieEnd :: Tiable a => a -> Bool
+ Music.Score.Ties: isTieEndBeginning :: Tiable a => a -> (Bool, Bool)
+ Music.Score.Ties: splitTiesAt :: Tiable a => [Duration] -> Voice a -> [Voice a]
+ Music.Time.Aligned: aligned :: Time -> LocalDuration -> v -> Aligned v
+ Music.Time.Aligned: data Aligned v
+ Music.Time.Aligned: instance HasDuration v => HasDuration (Aligned v)
+ Music.Time.Aligned: instance HasDuration v => HasPosition (Aligned v)
+ Music.Time.Aligned: instance Show a => Show (Aligned a)
+ Music.Time.Aligned: instance Transformable v => Transformable (Aligned v)
+ Music.Time.Aligned: renderAligned :: HasDuration a => (Span -> a -> b) -> Aligned a -> b
+ Music.Time.Aligned: renderAlignedDuration :: Aligned Duration -> Span
+ Music.Time.Aligned: renderAlignedNote :: Aligned (Note a) -> Event a
+ Music.Time.Aligned: renderAlignedVoice :: Aligned (Voice a) -> Score a
+ Music.Time.Event: data Event a
+ Music.Time.Event: event :: Iso (Span, a) (Span, b) (Event a) (Event b)
+ Music.Time.Event: eventee :: (Transformable a, Transformable b) => Lens (Event a) (Event b) a b
+ Music.Time.Event: instance (Comonad f, Comonad g) => Comonad (Compose f g)
+ Music.Time.Event: instance (Functor f, Monad f, Monad g, Traversable g) => Monad (Compose f g)
+ Music.Time.Event: instance (Real (f (g a)), Ord1 f, Ord1 g, Ord a, Functor f) => Real (Compose f g a)
+ Music.Time.Event: instance (RealFrac (f (g a)), Ord1 f, Ord1 g, Ord a, Functor f) => RealFrac (Compose f g a)
+ Music.Time.Event: instance (Show a, Transformable a) => Show (Event a)
+ Music.Time.Event: instance Applicative Event
+ Music.Time.Event: instance Comonad Event
+ Music.Time.Event: instance Eq a => Eq (Event a)
+ Music.Time.Event: instance Eq a => Eq1 (Couple a)
+ Music.Time.Event: instance Eq1 AddMeta
+ Music.Time.Event: instance Floating (f (g a)) => Floating (Compose f g a)
+ Music.Time.Event: instance Floating a => Floating (Event a)
+ Music.Time.Event: instance Foldable Event
+ Music.Time.Event: instance Fractional (f (g a)) => Fractional (Compose f g a)
+ Music.Time.Event: instance Fractional a => Fractional (Event a)
+ Music.Time.Event: instance Functor Event
+ Music.Time.Event: instance HasDuration (Event a)
+ Music.Time.Event: instance HasMeta (Event a)
+ Music.Time.Event: instance HasPosition (Event a)
+ Music.Time.Event: instance IsDynamics a => IsDynamics (Event a)
+ Music.Time.Event: instance IsInterval a => IsInterval (Event a)
+ Music.Time.Event: instance IsPitch a => IsPitch (Event a)
+ Music.Time.Event: instance IsString a => IsString (Event a)
+ Music.Time.Event: instance Monad Event
+ Music.Time.Event: instance Num (f (g a)) => Num (Compose f g a)
+ Music.Time.Event: instance Num a => Num (Event a)
+ Music.Time.Event: instance Ord a => Ord (Event a)
+ Music.Time.Event: instance Ord a => Ord1 (Couple a)
+ Music.Time.Event: instance Ord1 AddMeta
+ Music.Time.Event: instance Real a => Real (Event a)
+ Music.Time.Event: instance RealFrac a => RealFrac (Event a)
+ Music.Time.Event: instance Rewrapped (Event a) (Event b)
+ Music.Time.Event: instance Transformable (Event a)
+ Music.Time.Event: instance Traversable AddMeta
+ Music.Time.Event: instance Traversable Event
+ Music.Time.Event: instance Typeable Event
+ Music.Time.Event: instance Wrapped (Event a)
+ Music.Time.Event: spanEvent :: Iso' Span (Event ())
+ Music.Time.Event: triple :: Iso (Event a) (Event b) (Time, Duration, a) (Time, Duration, b)
+ Music.Time.Internal.Util: _zipList :: Iso [a] [b] (ZipList a) (ZipList b)
+ Music.Time.Note: durationNote :: Iso' Duration (Note ())
+ Music.Time.Note: instance Floating a => Floating (Note a)
+ Music.Time.Note: instance Fractional a => Fractional (Note a)
+ Music.Time.Note: instance Num a => Num (Note a)
+ Music.Time.Note: instance Ord a => Ord (Note a)
+ Music.Time.Note: instance Real a => Real (Note a)
+ Music.Time.Note: instance RealFrac a => RealFrac (Note a)
+ Music.Time.Note: notee :: (Transformable a, Transformable b) => Lens (Note a) (Note b) a b
+ Music.Time.Placed: data Placed a
+ Music.Time.Placed: instance (Show a, Transformable a) => Show (Placed a)
+ Music.Time.Placed: instance Applicative Placed
+ Music.Time.Placed: instance Comonad Placed
+ Music.Time.Placed: instance Eq a => Eq (Placed a)
+ Music.Time.Placed: instance Foldable Placed
+ Music.Time.Placed: instance Functor Placed
+ Music.Time.Placed: instance IsDynamics a => IsDynamics (Placed a)
+ Music.Time.Placed: instance IsInterval a => IsInterval (Placed a)
+ Music.Time.Placed: instance IsPitch a => IsPitch (Placed a)
+ Music.Time.Placed: instance IsString a => IsString (Placed a)
+ Music.Time.Placed: instance Monad Placed
+ Music.Time.Placed: instance Ord a => Ord (Placed a)
+ Music.Time.Placed: instance Rewrapped (Placed a) (Placed b)
+ Music.Time.Placed: instance Transformable a => Transformable (Placed a)
+ Music.Time.Placed: instance Traversable Placed
+ Music.Time.Placed: instance Typeable Placed
+ Music.Time.Placed: instance Wrapped (Placed a)
+ Music.Time.Placed: placed :: Iso (Time, a) (Time, b) (Placed a) (Placed b)
+ Music.Time.Placed: placee :: (Transformable a, Transformable b) => Lens (Placed a) (Placed b) a b
+ Music.Time.Position: _era :: (HasPosition a, HasPosition a) => a -> Span
+ Music.Time.Position: _offset :: HasPosition a => a -> Time
+ Music.Time.Position: _onset :: HasPosition a => a -> Time
+ Music.Time.Position: delayRelative :: (HasPosition a, Transformable a) => Duration -> Duration -> a -> a
+ Music.Time.Position: delayRelativeMidpoint :: (HasPosition a, Transformable a) => Duration -> a -> a
+ Music.Time.Position: delayRelativeOffset :: (HasPosition a, Transformable a) => Duration -> a -> a
+ Music.Time.Position: delayRelativeOnset :: (HasPosition a, Transformable a) => Duration -> a -> a
+ Music.Time.Position: stretchRelative :: (HasPosition a, Transformable a) => Duration -> Duration -> a -> a
+ Music.Time.Position: stretchRelativeMidpoint :: (HasPosition a, Transformable a) => Duration -> a -> a
+ Music.Time.Position: stretchRelativeOffset :: (HasPosition a, Transformable a) => Duration -> a -> a
+ Music.Time.Position: stretchRelativeOnset :: (HasPosition a, Transformable a) => Duration -> a -> a
+ Music.Time.Position: transformRelative :: (HasPosition a, Transformable a) => Duration -> Span -> a -> a
+ Music.Time.Position: transformRelativeMidpoint :: (HasPosition a, Transformable a) => Span -> a -> a
+ Music.Time.Position: transformRelativeOffset :: (HasPosition a, Transformable a) => Span -> a -> a
+ Music.Time.Position: transformRelativeOnset :: (HasPosition a, Transformable a) => Span -> a -> a
+ Music.Time.Reactive: instance Reversible (Reactive a)
+ Music.Time.Score: filterTriples :: (Time -> Duration -> a -> Bool) -> Score a -> Score a
+ Music.Time.Score: instance (Show a, Transformable a) => Show (Score' a)
+ Music.Time.Score: instance Alternative Score'
+ Music.Time.Score: instance Applicative Score'
+ Music.Time.Score: instance Eq a => Eq (Score' a)
+ Music.Time.Score: instance Foldable Score'
+ Music.Time.Score: instance Functor Score'
+ Music.Time.Score: instance HasDuration (Score' a)
+ Music.Time.Score: instance HasPosition (Score' a)
+ Music.Time.Score: instance Monad Score'
+ Music.Time.Score: instance MonadPlus Score'
+ Music.Time.Score: instance Monoid (Score' a)
+ Music.Time.Score: instance Rewrapped (Score' a) (Score' b)
+ Music.Time.Score: instance Semigroup (Score' a)
+ Music.Time.Score: instance Transformable (Score' a)
+ Music.Time.Score: instance Traversable Score'
+ Music.Time.Score: instance Typeable Score'
+ Music.Time.Score: instance Wrapped (Score' a)
+ Music.Time.Score: mapFilterTriples :: (Time -> Duration -> a -> Maybe b) -> Score a -> Score b
+ Music.Time.Score: mapTriples :: (Time -> Duration -> a -> b) -> Score a -> Score b
+ Music.Time.Score: triples :: Lens (Score a) (Score b) [(Time, Duration, a)] [(Time, Duration, b)]
+ Music.Time.Score: unsafeTriples :: Iso (Score a) (Score b) [(Time, Duration, a)] [(Time, Duration, b)]
+ Music.Time.Track: instance Transformable a => Transformable (Track a)
+ Music.Time.Track: placeds :: Lens (Track a) (Track b) [Placed a] [Placed b]
+ Music.Time.Types: instance VectorSpace Span
+ Music.Time.Types: pointOffsets :: AffineSpace p => p -> [p] -> [Diff p]
+ Music.Time.Types: type LocalDuration = Duration
+ Music.Time.Voice: durationsVoice :: Iso' [Duration] (Voice ())
+ Music.Time.Voice: erasRelative :: Time -> Voice a -> [Span]
+ Music.Time.Voice: homoToPolyphonic :: Voice [a] -> [Voice a]
+ Music.Time.Voice: instance Cons (Voice a) (Voice b) (Note a) (Note b)
+ Music.Time.Voice: instance Ord a => Ord (Voice a)
+ Music.Time.Voice: instance Snoc (Voice a) (Voice b) (Note a) (Note b)
+ Music.Time.Voice: mergeIfSameDuration :: Voice a -> Voice b -> Maybe (Voice (a, b))
+ Music.Time.Voice: mergeIfSameDurationWith :: (a -> b -> c) -> Voice a -> Voice b -> Maybe (Voice c)
+ Music.Time.Voice: midpointsRelative :: Time -> Voice a -> [Time]
+ Music.Time.Voice: notes :: Lens (Voice a) (Voice b) [Note a] [Note b]
+ Music.Time.Voice: offsetsRelative :: Time -> Voice a -> [Time]
+ Music.Time.Voice: onsetsRelative :: Time -> Voice a -> [Time]
+ Music.Time.Voice: pairs :: Lens (Voice a) (Voice b) [(Duration, a)] [(Duration, b)]
+ Music.Time.Voice: sameDurations :: Voice a -> Voice b -> Bool
+ Music.Time.Voice: unsafeNotes :: Iso (Voice a) (Voice b) [Note a] [Note b]
+ Music.Time.Voice: unsafePairs :: Iso (Voice a) (Voice b) [(Duration, a)] [(Duration, b)]
- Music.Score.Meta: addMetaNote :: (AttributeClass a, HasMeta b) => Note a -> b -> b
+ Music.Score.Meta: addMetaNote :: (AttributeClass a, HasMeta b) => Event a -> b -> b
- Music.Score.Ties: class Tiable a where beginTie = fst . toTied endTie = snd . toTied toTied a = (beginTie a, endTie a)
+ Music.Score.Ties: class Tiable a where beginTie = fst . toTied endTie = snd . toTied toTied a = (beginTie a, endTie a) isTieBeginning = snd . isTieEndBeginning isTieEnd = fst . isTieEndBeginning
- Music.Time.Behavior: turnOff :: Num a => Behavior a
+ Music.Time.Behavior: turnOff :: Behavior Integer
- Music.Time.Behavior: turnOn :: Num a => Behavior a
+ Music.Time.Behavior: turnOn :: Behavior Integer
- Music.Time.Internal.Util: tripped :: Iso ((a, b), c) ((a', b'), c') (a, b, c) (a', b', c')
+ Music.Time.Internal.Util: tripped :: Iso ((a, b), c) ((d, e), f) (a, b, c) (d, e, f)
- Music.Time.Note: note :: Iso (Span, a) (Span, b) (Note a) (Note b)
+ Music.Time.Note: note :: Iso (Duration, a) (Duration, b) (Note a) (Note b)
- Music.Time.Past: Future :: (Max Time, a) -> Future a
+ Music.Time.Past: Future :: (Max (Maybe Time), a) -> Future a
- Music.Time.Past: Past :: (Min Time, a) -> Past a
+ Music.Time.Past: Past :: (Min (Maybe Time), a) -> Past a
- Music.Time.Past: getFuture :: Future a -> (Max Time, a)
+ Music.Time.Past: getFuture :: Future a -> (Max (Maybe Time), a)
- Music.Time.Past: getPast :: Past a -> (Min Time, a)
+ Music.Time.Past: getPast :: Past a -> (Min (Maybe Time), a)
- Music.Time.Position: class HasDuration a => HasPosition a where _position x = alerp (_onset x) (_offset x) _onset = (`_position` 0) _offset = (`_position` 1.0)
+ Music.Time.Position: class HasDuration a => HasPosition a where _position x = alerp a b where (a, b) = (_era x) ^. range _era x = x `_position` 0 <-> x `_position` 1
- Music.Time.Reactive: intermediate :: Transformable a => Reactive a -> [Note a]
+ Music.Time.Reactive: intermediate :: Transformable a => Reactive a -> [Event a]
- Music.Time.Reactive: splitReactive :: Reactive a -> Either a ((a, Time), [Note a], (Time, a))
+ Music.Time.Reactive: splitReactive :: Reactive a -> Either a ((a, Time), [Event a], (Time, a))
- Music.Time.Score: events :: Lens (Score a) (Score b) [(Time, Duration, a)] [(Time, Duration, b)]
+ Music.Time.Score: events :: Lens (Score a) (Score b) [Event a] [Event b]
- Music.Time.Score: score :: Getter [Note a] (Score a)
+ Music.Time.Score: score :: Getter [Event a] (Score a)
- Music.Time.Score: unsafeEvents :: Iso (Score a) (Score b) [(Time, Duration, a)] [(Time, Duration, b)]
+ Music.Time.Score: unsafeEvents :: Iso (Score a) (Score b) [Event a] [Event b]
- Music.Time.Segment: apSegments :: Voice (Segment a) -> Stretched (Segment a)
+ Music.Time.Segment: apSegments :: Voice (Segment a) -> Note (Segment a)
- Music.Time.Segment: apSegments' :: Stretched (Segment a) -> Stretched (Segment a) -> Stretched (Segment a)
+ Music.Time.Segment: apSegments' :: Note (Segment a) -> Note (Segment a) -> Note (Segment a)
- Music.Time.Segment: bounded :: Iso (Note (Segment a)) (Note (Segment b)) (Bound (Behavior a)) (Bound (Behavior b))
+ Music.Time.Segment: bounded :: Iso (Event (Segment a)) (Event (Segment b)) (Bound (Behavior a)) (Bound (Behavior b))
- Music.Time.Segment: bounded' :: Iso' (Note (Segment a)) (Bound (Behavior a))
+ Music.Time.Segment: bounded' :: Iso' (Event (Segment a)) (Bound (Behavior a))
- Music.Time.Segment: turnOff :: Num a => Behavior a
+ Music.Time.Segment: turnOff :: Behavior Integer
- Music.Time.Segment: turnOn :: Num a => Behavior a
+ Music.Time.Segment: turnOn :: Behavior Integer
- Music.Time.Track: track :: Getter [Delayed a] (Track a)
+ Music.Time.Track: track :: Getter [Placed a] (Track a)
- Music.Time.Types: offsetPoints :: AffineSpace a => a -> [Diff a] -> [a]
+ Music.Time.Types: offsetPoints :: AffineSpace p => p -> [Diff p] -> [p]
- Music.Time.Voice: voice :: Getter [Stretched a] (Voice a)
+ Music.Time.Voice: voice :: Getter [Note a] (Voice a)

Files

music-score.cabal view
@@ -1,6 +1,6 @@  name:                   music-score-version:                1.7.2+version:                1.8 author:                 Hans Hoglund maintainer:             Hans Hoglund license:                BSD3@@ -23,7 +23,7 @@ library     build-depends:      base                    >= 4 && < 5,                         aeson                   >= 0.7.0.6 && < 1,-                        lens                    >= 4.3.3 && < 4.4,+                        lens                    >= 4.6      && < 4.7,                         process                 >= 1.2 && < 1.3,                         containers,                         void,@@ -31,7 +31,6 @@                         data-default,                         average                 >= 0.6 && < 1,                         semigroups              >= 0.13.0.1 && < 1,-                        semigroupoids,                         contravariant           >= 1.2 && < 2,                         comonad                 >= 4.2.2 && < 5,                         bifunctors              >= 4.1.1.1 && < 5,@@ -39,6 +38,7 @@                         distributive            >= 0.4.4 && < 5,                         adjunctions             >= 4.2 && < 5,                         transformers            >= 0.3.0.0 && < 0.5,+                        transformers-compat     >= 0.3.3.4 && < 0.5,                         mtl                     >= 2.1.2 && < 2.3,                         monadplus,                         NumInstances,@@ -46,11 +46,10 @@                         HCodecs                 >= 0.5 && < 0.6,                         vector-space            >= 0.8.7 && < 0.9,                         vector-space-points     >= 0.2 && < 0.3,-                        musicxml2               == 1.7.2,-                        lilypond                == 1.7.2,-                        music-pitch-literal     == 1.7.2,-                        music-dynamics-literal  == 1.7.2,-+                        musicxml2               == 1.8,+                        lilypond                == 1.8,+                        music-pitch-literal     == 1.8,+                        music-dynamics-literal  == 1.8,                         prettify,                         parsec     exposed-modules:    Data.Clipped@@ -70,9 +69,10 @@                         Music.Time.Reverse                         Music.Time.Juxtapose                         Music.Time.Rest-                        Music.Time.Stretched-                        Music.Time.Delayed+                        Music.Time.Aligned                         Music.Time.Note+                        Music.Time.Placed+                        Music.Time.Event                         Music.Time.Future                         Music.Time.Past                         Music.Time.Nominal@@ -126,14 +126,14 @@                         Music.Score.Import.Abc                         Music.Score.Import.Lilypond                         Music.Score.Import.Midi-                        Music.Score.Instances                         -- We expose these to allow GHCI development                         Music.Time.Internal.Convert                         Music.Time.Internal.Util                         Music.Time.Internal.Transform                         Music.Time.Internal.Quantize+                        Music.Score.Internal.Instances                         Music.Score.Internal.Util                         Music.Score.Internal.Export     hs-source-dirs:     src     default-language:   Haskell2010-    --ghc-options:        -fwarn-unused-imports+    ghc-options:        -fno-warn-typed-holes
src/Data/Functor/Context.hs view
@@ -5,8 +5,10 @@  module Data.Functor.Context (         Ctxt(..),+        toCtxt,         mapCtxt,         extractCtxt,+        addCtxt,   ) where  import Control.Comonad@@ -14,10 +16,14 @@ import Control.Lens.Wrapped import Control.Lens.Iso --- TODO use newtype and derivice Functor, Comonad etc+-- | A value with a possible predecessor and successor.+-- Can be used to traverse values with their immediate context. newtype Ctxt a = Ctxt { getCtxt :: (Maybe a, a, Maybe a) }-  deriving (Functor)+  deriving (Functor, Eq, Ord) +instance Show a => Show (Ctxt a) where+  show (Ctxt vs) = "toCtxt " ++ show vs+ instance Wrapped (Ctxt a) where   type Unwrapped (Ctxt a) = (Maybe a, a, Maybe a)   _Wrapped' = iso getCtxt Ctxt@@ -36,9 +42,17 @@   -- duplicate (Ctxt (Nothing,x,Just a)) = Ctxt (Nothing, Ctxt (Nothing, x, Just a), Just a)   -- duplicate (Ctxt (Just b,x,Just a)) = Ctxt (b, Ctxt (b, x, Just a), Just a) +toCtxt = Ctxt+ mapCtxt :: (a -> b) -> Ctxt a -> Ctxt b mapCtxt = fmap  extractCtxt :: Ctxt a -> a extractCtxt (Ctxt (_,x,_)) = x++addCtxt :: [a] -> [Ctxt a]+addCtxt = fmap Ctxt . withPrevNext+  where+    withPrevNext :: [a] -> [(Maybe a, a, Maybe a)]+    withPrevNext xs = zip3 (pure Nothing ++ fmap Just xs) xs (fmap Just (tail xs) ++ repeat Nothing)     
src/Music/Score.hs view
@@ -12,7 +12,6 @@ -------------------------------------------------------------------------------------  module Music.Score (-        -- * Prerequisites         module Control.Lens,         module Control.Applicative,         module Control.Monad,@@ -24,9 +23,6 @@          module Music.Time,         -- module Music.Score.Combinators,--        -- * Music representation-        -- ** Musical elements         module Music.Score.Part,         module Music.Score.Pitch,         module Music.Score.Dynamics,@@ -37,12 +33,9 @@         module Music.Score.Harmonics,         module Music.Score.Color, -        -- ** Miscellaneous         module Music.Score.Ties,         module Music.Score.Phrases,-        -- module Music.Score.Clef, -        -- ** Meta-information         module Music.Score.Meta,         module Music.Score.Meta.Title,         module Music.Score.Meta.Attribution,@@ -55,12 +48,10 @@         module Music.Score.Meta.Tempo,         module Music.Score.Meta.Annotations, -        -- * Import and export         module Music.Score.Import.Abc,         module Music.Score.Import.Lilypond,         module Music.Score.Import.Midi, -        -- module Music.Score.Export.Abc,         module Music.Score.Export.Backend,         module Music.Score.Export.NoteList,         module Music.Score.Export.Midi,@@ -92,7 +83,6 @@ import           Music.Time                     hiding (time)  import           Music.Score.Articulation--- import           Music.Score.Clef import           Music.Score.Color import           Music.Score.Dynamics import           Music.Score.Export.Backend@@ -107,7 +97,7 @@ import           Music.Score.Import.Abc import           Music.Score.Import.Lilypond import           Music.Score.Import.Midi-import           Music.Score.Instances+import           Music.Score.Internal.Instances import           Music.Score.Meta import           Music.Score.Meta.Annotations import           Music.Score.Meta.Attribution
src/Music/Score/Articulation.hs view
@@ -187,17 +187,15 @@ type instance Articulation (Either c a)       = Articulation a type instance SetArticulation b (Either c a)  = Either c (SetArticulation b a) +type instance Articulation (Event a) = Articulation a+type instance SetArticulation g (Event a) = Event (SetArticulation g a)+type instance Articulation (Placed a) = Articulation a+type instance SetArticulation g (Placed a) = Placed (SetArticulation g a) type instance Articulation (Note a) = Articulation a type instance SetArticulation g (Note a) = Note (SetArticulation g a)-type instance Articulation (Delayed a) = Articulation a-type instance SetArticulation g (Delayed a) = Delayed (SetArticulation g a)-type instance Articulation (Stretched a) = Articulation a-type instance SetArticulation g (Stretched a) = Stretched (SetArticulation g a)  type instance Articulation (Voice a) = Articulation a type instance SetArticulation b (Voice a) = Voice (SetArticulation b a)-type instance Articulation (Chord a) = Articulation a-type instance SetArticulation b (Chord a) = Chord (SetArticulation b a) type instance Articulation (Track a) = Articulation a type instance SetArticulation b (Track a) = Track (SetArticulation b a) type instance Articulation (Score a) = Articulation a@@ -221,30 +219,34 @@   -instance (HasArticulations a b) => HasArticulations (Note a) (Note b) where-  articulations = _Wrapped . whilstL articulations+instance (HasArticulations a b) => HasArticulations (Event a) (Event b) where+  articulations = from event . whilstL articulations -instance (HasArticulation a b) => HasArticulation (Note a) (Note b) where-  articulation = _Wrapped . whilstL articulation+instance (HasArticulation a b) => HasArticulation (Event a) (Event b) where+  articulation = from event . whilstL articulation -instance (HasArticulations a b) => HasArticulations (Delayed a) (Delayed b) where+instance (HasArticulations a b) => HasArticulations (Placed a) (Placed b) where   articulations = _Wrapped . whilstLT articulations -instance (HasArticulation a b) => HasArticulation (Delayed a) (Delayed b) where+instance (HasArticulation a b) => HasArticulation (Placed a) (Placed b) where   articulation = _Wrapped . whilstLT articulation -instance (HasArticulations a b) => HasArticulations (Stretched a) (Stretched b) where+instance (HasArticulations a b) => HasArticulations (Note a) (Note b) where   articulations = _Wrapped . whilstLD articulations -instance (HasArticulation a b) => HasArticulation (Stretched a) (Stretched b) where+instance (HasArticulation a b) => HasArticulation (Note a) (Note b) where   articulation = _Wrapped . whilstLD articulation   instance HasArticulations a b => HasArticulations (Voice a) (Voice b) where   articulations = traverse . articulations +{-+type instance Articulation (Chord a) = Articulation a+type instance SetArticulation b (Chord a) = Chord (SetArticulation b a) instance HasArticulations a b => HasArticulations (Chord a) (Chord b) where   articulations = traverse . articulations+-}  instance HasArticulations a b => HasArticulations (Track a) (Track b) where   articulations = traverse . articulations@@ -254,7 +256,7 @@     _Wrapped . _2   -- into NScore     . _Wrapped     . traverse-    . _Wrapped      -- this needed?+    . from event    -- this needed?     . whilstL articulations  type instance Articulation (Couple c a)        = Articulation a@@ -439,6 +441,7 @@ deriving instance Reversible a => Reversible (ArticulationT p a)  instance (Tiable n, Tiable a) => Tiable (ArticulationT n a) where+  isTieEndBeginning (ArticulationT (_,a)) = isTieEndBeginning a   toTied (ArticulationT (d,a)) = (ArticulationT (d1,a1), ArticulationT (d2,a2))     where       (a1,a2) = toTied a
src/Music/Score/Color.hs view
@@ -112,6 +112,7 @@   (<>) = liftA2 (<>)  instance Tiable a => Tiable (ColorT a) where+  isTieEndBeginning (ColorT (Couple (_,a))) = isTieEndBeginning a   toTied (ColorT (Couple (n,a))) = (ColorT $ Couple (n,b), ColorT $ Couple (n,c))      where        (b,c) = toTied a
src/Music/Score/Dynamics.hs view
@@ -177,17 +177,15 @@ type instance Dynamic (Either c a)        = Dynamic a type instance SetDynamic b (Either c a)   = Either c (SetDynamic b a) -type instance Dynamic (Note a)            = Dynamic a-type instance SetDynamic b (Note a)       = Note (SetDynamic b a)-type instance Dynamic (Delayed a)         = Dynamic a-type instance SetDynamic b (Delayed a)    = Delayed (SetDynamic b a)-type instance Dynamic (Stretched a)       = Dynamic a-type instance SetDynamic b (Stretched a)  = Stretched (SetDynamic b a)+type instance Dynamic (Event a)            = Dynamic a+type instance SetDynamic b (Event a)       = Event (SetDynamic b a)+type instance Dynamic (Placed a)         = Dynamic a+type instance SetDynamic b (Placed a)    = Placed (SetDynamic b a)+type instance Dynamic (Note a)       = Dynamic a+type instance SetDynamic b (Note a)  = Note (SetDynamic b a)  type instance Dynamic (Voice a)       = Dynamic a type instance SetDynamic b (Voice a)  = Voice (SetDynamic b a)-type instance Dynamic (Chord a)       = Dynamic a-type instance SetDynamic b (Chord a)  = Chord (SetDynamic b a) type instance Dynamic (Track a)       = Dynamic a type instance SetDynamic b (Track a)  = Track (SetDynamic b a) type instance Dynamic (Score a)       = Dynamic a@@ -210,24 +208,24 @@   -instance (HasDynamics a b) => HasDynamics (Note a) (Note b) where-  dynamics = _Wrapped . whilstL dynamics+instance (HasDynamics a b) => HasDynamics (Event a) (Event b) where+  dynamics = from event . whilstL dynamics -instance (HasDynamic a b) => HasDynamic (Note a) (Note b) where-  dynamic = _Wrapped . whilstL dynamic+instance (HasDynamic a b) => HasDynamic (Event a) (Event b) where+  dynamic = from event . whilstL dynamic  -instance (HasDynamics a b) => HasDynamics (Delayed a) (Delayed b) where+instance (HasDynamics a b) => HasDynamics (Placed a) (Placed b) where   dynamics = _Wrapped . whilstLT dynamics -instance (HasDynamic a b) => HasDynamic (Delayed a) (Delayed b) where+instance (HasDynamic a b) => HasDynamic (Placed a) (Placed b) where   dynamic = _Wrapped . whilstLT dynamic  -instance (HasDynamics a b) => HasDynamics (Stretched a) (Stretched b) where+instance (HasDynamics a b) => HasDynamics (Note a) (Note b) where   dynamics = _Wrapped . whilstLD dynamics -instance (HasDynamic a b) => HasDynamic (Stretched a) (Stretched b) where+instance (HasDynamic a b) => HasDynamic (Note a) (Note b) where   dynamic = _Wrapped . whilstLD dynamic  @@ -237,15 +235,19 @@ instance HasDynamics a b => HasDynamics (Track a) (Track b) where   dynamics = traverse . dynamics +{-+type instance Dynamic (Chord a)       = Dynamic a+type instance SetDynamic b (Chord a)  = Chord (SetDynamic b a) instance HasDynamics a b => HasDynamics (Chord a) (Chord b) where   dynamics = traverse . dynamics+-}  instance (HasDynamics a b) => HasDynamics (Score a) (Score b) where   dynamics =     _Wrapped . _2   -- into NScore     . _Wrapped     . traverse-    . _Wrapped      -- this needed?+    . from event    -- this needed?     . whilstL dynamics  type instance Dynamic      (Behavior a) = Behavior a@@ -454,6 +456,7 @@ deriving instance Reversible a => Reversible (DynamicT p a)  instance (Tiable n, Tiable a) => Tiable (DynamicT n a) where+  isTieEndBeginning (DynamicT (_,a)) = isTieEndBeginning a   toTied (DynamicT (d,a)) = (DynamicT (d1,a1), DynamicT (d2,a2))     where       (a1,a2) = toTied a
src/Music/Score/Export/ArticulationNotation.hs view
@@ -42,7 +42,7 @@ import Data.Functor.Adjunction (unzipR) import Control.Lens -- () import Music.Score.Articulation-import Music.Score.Instances+-- import Music.Score.Instances import Music.Score.Ties import Music.Time 
src/Music/Score/Export/Lilypond.hs view
@@ -315,7 +315,7 @@             1 -> Lilypond.Alto             2 -> Lilypond.Bass           addStaffInfo  = (,) $ StaffInfo { staffName = name, staffClef = clef }-          splitIntoBars = splitTiesVoiceAt+          splitIntoBars = splitTiesAt        exportBar timeSignature         = LyBar@@ -324,7 +324,7 @@        where          addBarInfo = (,) $ BarInfo timeSignature -      quantizeBar = mapWithDur LyContext . rewrite . handleErrors . quantize . view eventsV+      quantizeBar = mapWithDur LyContext . rewrite . handleErrors . quantize . view pairs         where           -- FIXME propagate quantization errors           handleErrors (Left e)  = error $ "Quantization failed: " ++ e
src/Music/Score/Export/Midi.hs view
@@ -163,7 +163,7 @@       setProgramChannel ch prg = ([(0, Midi.ProgramChange ch prg)] <>) . fmap (fmap $ setC ch)        scoreToMidiTrack :: Score Midi.Message -> Midi.Track Midi.Ticks-      scoreToMidiTrack = fmap (\(t,_,x) -> (round ((t .-. 0) ^* divisions), x)) . toRelative . (^. events)+      scoreToMidiTrack = fmap (\(t,_,x) -> (round ((t .-. 0) ^* divisions), x)) . toRelative . (^. triples)        -- Hardcoded values for Midi export       -- We always generate MultiTrack (type 1) files with division 1024@@ -185,11 +185,12 @@   exportScore _ xs = MidiScore [((getMidiChannel (xs^?!parts), getMidiProgram (xs^?!parts)), fmap Identity $ voiceToScore xs)]     where       voiceToScore :: Voice a -> Score a-      voiceToScore = error "FIXME"+      voiceToScore = renderAlignedVoice . aligned (0 :: Time) (0 :: LocalDuration)  instance (HasPart' a, Ord (Part a), HasMidiProgram (Part a)) => HasBackendScore Midi (Score a) where   type BackendScoreEvent Midi (Score a) = a-  exportScore _ xs = MidiScore (map (\(p,sc) -> ((getMidiChannel p, getMidiProgram p), fmap Identity sc)) $ extractPartsWithInfo $ fixTempo xs)+  exportScore _ xs = MidiScore (map (\(p,sc) -> ((getMidiChannel p, getMidiProgram p), fmap Identity sc)) +    $ extractPartsWithInfo $ fixTempo $ normalizeScore xs)     where       -- We actually want to extract *all* tempo changes and transform the score appropriately       -- For the time being, we assume the whole score has the same tempo
src/Music/Score/Export/MusicXml.hs view
@@ -306,7 +306,7 @@             1 -> (MusicXml.CClef, 3)             2 -> (MusicXml.FClef, 4)           addStaffInfo  = (,) $ StaffInfo { staffClef = clef }-          splitIntoBars = splitTiesVoiceAt+          splitIntoBars = splitTiesAt        exportBar timeSignature         = XmlBar@@ -315,7 +315,7 @@        where          addBarInfo = (,) $ BarInfo timeSignature -      quantizeBar = mapWithDur XmlContext . rewrite . handleErrors . quantize . view eventsV+      quantizeBar = mapWithDur XmlContext . rewrite . handleErrors . quantize . view pairs         where           -- FIXME propagate quantization errors           handleErrors (Left e)  = error $ "Quantization failed: " ++ e
src/Music/Score/Export/SuperCollider.hs view
@@ -124,7 +124,7 @@       composeTracksInParallel = (\x -> "Ppar([" ++ x ++ "])") . Data.List.intercalate ", "              exportTrack :: [(Duration, Maybe ScEvent)] -> String-      exportTrack events = "Pbind("+      exportTrack triples = "Pbind("         ++ "\\dur, Pseq(" ++ show durs ++ ")"         ++ ", "         ++ "\\midinote, Pseq(" ++ showRestList pitches ++ ")"@@ -134,18 +134,18 @@             . Data.List.intercalate ", "              . map (maybe "\\rest" show)    -          -- events :: ScEvent+          -- triples :: ScEvent           durs    :: [Double]           pitches :: [Maybe Double]           ampls   :: [Maybe Double]-          durs    = map (realToFrac . fst) events-          pitches = map (fmap fst . snd) events-          ampls   = map (fmap snd . snd) events+          durs    = map (realToFrac . fst) triples+          pitches = map (fmap fst . snd) triples+          ampls   = map (fmap snd . snd) triples             instance () => HasBackendScore SuperCollider (Voice (Maybe a)) where   type BackendScoreEvent SuperCollider (Voice (Maybe a)) = a-  exportScore _ xs = Identity <$> ScScore [view eventsV xs]+  exportScore _ xs = Identity <$> ScScore [view pairs xs]  instance (HasPart' a, Ord (Part a)) => HasBackendScore SuperCollider (Score a) where   type BackendScoreEvent SuperCollider (Score a) = a
− src/Music/Score/Instances.hs
@@ -1,343 +0,0 @@--{-# LANGUAGE ConstraintKinds            #-}-{-# LANGUAGE DeriveDataTypeable         #-}-{-# LANGUAGE DeriveFoldable             #-}-{-# LANGUAGE DeriveFunctor              #-}-{-# LANGUAGE FlexibleContexts           #-}-{-# LANGUAGE FlexibleInstances          #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MultiParamTypeClasses      #-}-{-# LANGUAGE NoMonomorphismRestriction  #-}-{-# LANGUAGE StandaloneDeriving         #-}-{-# LANGUAGE TypeFamilies               #-}------------------------------------------------------------------------------------------ |--- Copyright   : (c) Hans Hoglund 2012-2014------ License     : BSD-style------ Maintainer  : hans@hanshoglund.se--- Stability   : experimental--- Portability : non-portable (TF,GNTD)------ Provides miscellaneous instances.-------------------------------------------------------------------------------------------module Music.Score.Instances () where--import           Control.Applicative-import           Control.Comonad-import           Control.Lens             hiding (part, transform)-import           Control.Monad-import           Data.AffineSpace-import           Data.Default-import           Data.Monoid.Average-import           Data.Foldable-import           Data.Functor.Adjunction  (unzipR)-import           Data.Functor.Couple-import qualified Data.List                as List-import           Data.Maybe-import           Data.Ratio-import           Data.Semigroup-import           Data.Typeable-import           Data.VectorSpace hiding (Sum)-import           Data.Semigroup.Instances-import           Data.Functor.Context--import           Music.Dynamics.Literal-import           Music.Pitch.Alterable-import           Music.Pitch.Augmentable-import           Music.Pitch.Literal-import           Music.Score.Articulation-import           Music.Score.Color-import           Music.Score.Dynamics-import           Music.Score.Harmonics-import           Music.Score.Meta-import           Music.Score.Part-import           Music.Score.Pitch-import           Music.Score.Slide-import           Music.Score.Text-import           Music.Score.Ties-import           Music.Score.Tremolo-import           Music.Time---- ------------------------------------------------------------------------------------------- instance Semigroup a => Semigroup (DynamicT a) where---     DynamicT (d1, x1) <> DynamicT (d2, x2) = DynamicT (d1 <> d2, x1 <> x2)-instance Semigroup a => Semigroup (SlideT a) where-    (<>) = liftA2 (<>)-instance Semigroup a => Semigroup (TieT a) where-    TieT (t1, x1) <> TieT (t2, x2) = TieT (t1 <> t2, x1 <> x2)-    -- This instance is suspect: in general chord notes are not required to share ties,-    -- so this instance may be removed (provided that TieT is moved inside Chord for-    -- all Preludes). See #134-instance Semigroup a => Semigroup (HarmonicT a) where-    (<>) = liftA2 (<>)-instance Semigroup a => Semigroup (TextT a) where-    (<>) = liftA2 (<>)-instance Semigroup a => Semigroup (PartT n a) where-    PartT (v1,x1) <> PartT (v2,x2) = PartT (v1, x1 <> x2)----- -------------------------------------------------------------------------------------------- Aspect instaces (Pitch, Dynamics and Articulation) for PartT needs to go here,--- as the other aspects depends on partwise traversals etc-----type instance Pitch (PartT p a) = Pitch a-type instance SetPitch b (PartT p a) = PartT p (SetPitch b a)--instance HasPitch a b => HasPitch (PartT p a) (PartT p b) where-  pitch = _Wrapped . _2 . pitch-instance HasPitches a b => HasPitches (PartT p a) (PartT p b) where-  pitches = _Wrapped . _2 . pitches--type instance Pitch (DynamicT p a) = Pitch a-type instance SetPitch b (DynamicT p a) = DynamicT p (SetPitch b a)--instance HasPitch a b => HasPitch (DynamicT p a) (DynamicT p b) where-  pitch = _Wrapped . _2 . pitch-instance HasPitches a b => HasPitches (DynamicT p a) (DynamicT p b) where-  pitches = _Wrapped . _2 . pitches--type instance Pitch (ArticulationT p a) = Pitch a-type instance SetPitch b (ArticulationT p a) = ArticulationT p (SetPitch b a)--instance HasPitch a b => HasPitch (ArticulationT p a) (ArticulationT p b) where-  pitch = _Wrapped . _2 . pitch-instance HasPitches a b => HasPitches (ArticulationT p a) (ArticulationT p b) where-  pitches = _Wrapped . _2 . pitches----type instance Dynamic (PartT p a) = Dynamic a-type instance SetDynamic b (PartT p a) = PartT p (SetDynamic b a)--instance HasDynamic a b => HasDynamic (PartT p a) (PartT p b) where-  dynamic = _Wrapped . _2 . dynamic-instance HasDynamics a b => HasDynamics (PartT p a) (PartT p b) where-  dynamics = _Wrapped . _2 . dynamics--type instance Dynamic (ArticulationT p a) = Dynamic a-type instance SetDynamic b (ArticulationT p a) = ArticulationT p (SetDynamic b a)--instance HasDynamic a b => HasDynamic (ArticulationT p a) (ArticulationT p b) where-  dynamic = _Wrapped . _2 . dynamic-instance HasDynamics a b => HasDynamics (ArticulationT p a) (ArticulationT p b) where-  dynamics = _Wrapped . _2 . dynamics----type instance Articulation (PartT p a) = Articulation a-type instance SetArticulation b (PartT p a) = PartT p (SetArticulation b a)--instance HasArticulation a b => HasArticulation (PartT p a) (PartT p b) where-  articulation = _Wrapped . _2 . articulation-instance HasArticulations a b => HasArticulations (PartT p a) (PartT p b) where-  articulations = _Wrapped . _2 . articulations---- TODO move up?-type instance Pitch (ColorT a)        = Pitch a-type instance SetPitch g (ColorT a)   = ColorT (SetPitch g a)-instance (HasPitches a b) => HasPitches (ColorT a) (ColorT b) where-  pitches = _Wrapped . pitches-instance (HasPitch a b) => HasPitch (ColorT a) (ColorT b) where-  pitch = _Wrapped . pitch--type instance Dynamic (ColorT a)        = Dynamic a-type instance SetDynamic g (ColorT a)   = ColorT (SetDynamic g a)-instance (HasDynamics a b) => HasDynamics (ColorT a) (ColorT b) where-  dynamics = _Wrapped . dynamics-instance (HasDynamic a b) => HasDynamic (ColorT a) (ColorT b) where-  dynamic = _Wrapped . dynamic--type instance Articulation (ColorT a)        = Articulation a-type instance SetArticulation g (ColorT a)   = ColorT (SetArticulation g a)-instance (HasArticulations a b) => HasArticulations (ColorT a) (ColorT b) where-  articulations = _Wrapped . articulations-instance (HasArticulation a b) => HasArticulation (ColorT a) (ColorT b) where-  articulation = _Wrapped . articulation----- ---------------------------------------------------------------------------------------deriving instance HasTremolo a => HasTremolo (PartT n a)-deriving instance HasHarmonic a => HasHarmonic (PartT n a)-deriving instance HasSlide a => HasSlide (PartT n a)-deriving instance HasText a => HasText (PartT n a)---deriving instance HasTremolo a => HasTremolo (TieT a)-deriving instance HasHarmonic a => HasHarmonic (TieT a)-deriving instance HasSlide a => HasSlide (TieT a)-deriving instance HasText a => HasText (TieT a)------ TextT--instance Tiable a => Tiable (TextT a) where-  toTied (TextT (Couple (n,a))) = (TextT (Couple (n,b)), TextT (Couple (mempty,c))) where (b,c) = toTied a-deriving instance HasTremolo a => HasTremolo (TextT a)-deriving instance HasHarmonic a => HasHarmonic (TextT a)-deriving instance HasSlide a => HasSlide (TextT a)----- HarmonicT--instance Tiable a => Tiable (HarmonicT a) where-  -- toTied = unzipR . fmap toTied-  toTied (HarmonicT (Couple (n,a))) = (HarmonicT (Couple (n,b)), HarmonicT (Couple (mempty,c))) where (b,c) = toTied a-deriving instance HasTremolo a => HasTremolo (HarmonicT a)-deriving instance HasSlide a => HasSlide (HarmonicT a)-deriving instance HasText a => HasText (HarmonicT a)----- SlideT---instance Tiable a => Tiable (SlideT a) where-  toTied = unzipR . fmap toTied-deriving instance HasTremolo a => HasTremolo (SlideT a)-deriving instance HasHarmonic a => HasHarmonic (SlideT a)-deriving instance HasText a => HasText (SlideT a)-----deriving instance IsPitch a => IsPitch (TextT a)-deriving instance IsDynamics a => IsDynamics (TextT a)-deriving instance IsPitch a => IsPitch (HarmonicT a)-deriving instance IsDynamics a => IsDynamics (HarmonicT a)-deriving instance IsPitch a => IsPitch (SlideT a)-deriving instance IsDynamics a => IsDynamics (SlideT a)--deriving instance IsPitch a => IsPitch (ColorT a)-deriving instance IsDynamics a => IsDynamics (ColorT a)-deriving instance Transformable a => Transformable (ColorT a)-deriving instance Reversible a => Reversible (ColorT a)-deriving instance Alterable a => Alterable (ColorT a)-deriving instance Augmentable a => Augmentable (ColorT a)-deriving instance HasTremolo a => HasTremolo (ColorT a)-deriving instance HasHarmonic a => HasHarmonic (ColorT a)-deriving instance HasSlide a => HasSlide (ColorT a)-deriving instance HasText a => HasText (ColorT a)--deriving instance Transformable a => Transformable (SlideT a)-deriving instance Transformable a => Transformable (HarmonicT a)-deriving instance Transformable a => Transformable (TextT a)--deriving instance Reversible a => Reversible (SlideT a)-deriving instance Reversible a => Reversible (HarmonicT a)-deriving instance Reversible a => Reversible (TextT a)--deriving instance Alterable a => Alterable (SlideT a)-deriving instance Alterable a => Alterable (HarmonicT a)-deriving instance Alterable a => Alterable (TextT a)--deriving instance Augmentable a => Augmentable (SlideT a)-deriving instance Augmentable a => Augmentable (HarmonicT a)-deriving instance Augmentable a => Augmentable (TextT a)-------------------------------------------------------------------------------------------- Literal instances-----------------------------------------------------------------------------------------instance Alterable a => Alterable (Score a) where-    sharpen = fmap sharpen-    flatten = fmap flatten-deriving instance Alterable a => Alterable (TieT a)-deriving instance Alterable a => Alterable (PartT n a)-deriving instance Alterable a => Alterable (DynamicT n a)-deriving instance Alterable a => Alterable (ArticulationT n a)--instance Augmentable a => Augmentable (Score a) where-    augment = fmap augment-    diminish = fmap diminish-deriving instance Augmentable a => Augmentable (TieT a)-deriving instance Augmentable a => Augmentable (PartT n a)-deriving instance Augmentable a => Augmentable (DynamicT n a)-deriving instance Augmentable a => Augmentable (ArticulationT n a)----- ---------------------------------------------------------------------------------------- -- Num, Integral, Enum and Bounded--- ------------------------------------------------------------------------------------------- PartT--instance (Enum v, Eq v, Num a) => Num (PartT v a) where-    PartT (v,a) + PartT (_,b) = PartT (v,a+b)-    PartT (v,a) * PartT (_,b) = PartT (v,a*b)-    PartT (v,a) - PartT (_,b) = PartT (v,a-b)-    abs (PartT (v,a))          = PartT (v,abs a)-    signum (PartT (v,a))       = PartT (v,signum a)-    fromInteger a               = PartT (toEnum 0,fromInteger a)--instance (Enum v, Enum a) => Enum (PartT v a) where-    toEnum a = PartT (toEnum 0, toEnum a) -- TODO use def, mempty or minBound?-    fromEnum (PartT (v,a)) = fromEnum a--instance (Enum v, Bounded a) => Bounded (PartT v a) where-    minBound = PartT (toEnum 0, minBound)-    maxBound = PartT (toEnum 0, maxBound)--instance (Enum v, Ord v, Num a, Ord a, Real a) => Real (PartT v a) where-    toRational (PartT (v,a)) = toRational a--instance (Enum v, Ord v, Real a, Enum a, Integral a) => Integral (PartT v a) where-    PartT (v,a) `quotRem` PartT (_,b) = (PartT (v,q), PartT (v,r)) where (q,r) = a `quotRem` b-    toInteger (PartT (v,a)) = toInteger a------- TODO suspect instances--- We should remove both these after replacing [] by Chord in Preludes----instance Enum a => Enum [a] where-    toEnum a       = [toEnum a]-    fromEnum ([a]) = fromEnum a--instance Bounded a => Bounded [a] where-    minBound = [minBound]-    maxBound = [maxBound]----- TODO use wrapper type and replace withContext-type instance Dynamic (a,b,c) = (a,b,c)-type instance SetDynamic g (a,b,c) = g--instance Transformable a => Transformable (Maybe a) where-  transform s = fmap (transform s)-instance (Transformable a, Transformable b, Transformable c) => Transformable (a,b,c) where-  transform s (a,b,c) = (transform s a,transform s b,transform s c)---- TODO place for this?--- For use with single-note scores etc-instance Tiable a => Tiable (Score a) where-  beginTie = fmap beginTie-  endTie   = fmap endTie--instance Transformable a => Transformable (Ctxt a) where-  transform s = fmap (transform s)--instance Transformable a => Transformable (Average a) where-  transform s = fmap (transform s)--instance IsPitch a => IsPitch (Average a) where-  fromPitch = pure . fromPitch--instance IsInterval a => IsInterval (Average a) where-  fromInterval = pure . fromInterval--instance IsDynamics a => IsDynamics (Average a) where-  fromDynamics = pure . fromDynamics--
src/Music/Score/Internal/Export.hs view
@@ -79,7 +79,7 @@   where                                               defaultTimeSignature = time 4 4     timeSignatures = fmap swap -      $ view eventsV . fuse . reactiveToVoice' (0 <-> (score^.offset)) +      $ view pairs . fuse . reactiveToVoice' (0 <-> (score^.offset))        $ getTimeSignatures defaultTimeSignature score      -- Despite the fuse above we need retainUpdates here to prevent redundant repetition of time signatures@@ -88,7 +88,7 @@  -- | Convert a voice to a list of bars using the given bar durations. voiceToBars' :: Tiable a => [Duration] -> Voice (Maybe a) -> [[(Duration, Maybe a)]]-voiceToBars' barDurs = fmap (map (^. from stretched) . (^. stretcheds)) . splitTiesVoiceAt barDurs+voiceToBars' barDurs = fmap (map (^. from note) . (^. notes)) . splitTiesAt barDurs -- TODO remove prime from name  -- | Basic spelling for integral types.@@ -118,8 +118,8 @@ toMVoice = scoreToVoice . simultaneous  unvoice :: Voice b -> [(Duration, b)]-unvoice = toListOf (stretcheds . traverse . from stretched)--- unvoice = fmap (^. from stretched) . (^. stretcheds)+unvoice = toListOf (notes . traverse . from note)+-- unvoice = fmap (^. from note) . (^. notes) {-# DEPRECATED unvoice "Use 'unsafeEventsV'" #-}  
+ src/Music/Score/Internal/Instances.hs view
@@ -0,0 +1,346 @@++{-# LANGUAGE ConstraintKinds            #-}+{-# LANGUAGE DeriveDataTypeable         #-}+{-# LANGUAGE DeriveFoldable             #-}+{-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE FlexibleContexts           #-}+{-# LANGUAGE FlexibleInstances          #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses      #-}+{-# LANGUAGE NoMonomorphismRestriction  #-}+{-# LANGUAGE StandaloneDeriving         #-}+{-# LANGUAGE TypeFamilies               #-}++-------------------------------------------------------------------------------------+-- |+-- Copyright   : (c) Hans Hoglund 2012-2014+--+-- License     : BSD-style+--+-- Maintainer  : hans@hanshoglund.se+-- Stability   : experimental+-- Portability : non-portable (TF,GNTD)+--+-- Provides miscellaneous instances.+--+-------------------------------------------------------------------------------------++module Music.Score.Internal.Instances () where++import           Control.Applicative+import           Control.Comonad+import           Control.Lens             hiding (part, transform)+import           Control.Monad+import           Data.AffineSpace+import           Data.Default+import           Data.Monoid.Average+import           Data.Foldable+import           Data.Functor.Adjunction  (unzipR)+import           Data.Functor.Couple+import qualified Data.List                as List+import           Data.Maybe+import           Data.Ratio+import           Data.Semigroup+import           Data.Typeable+import           Data.VectorSpace hiding (Sum)+import           Data.Semigroup.Instances+import           Data.Functor.Context++import           Music.Dynamics.Literal+import           Music.Pitch.Alterable+import           Music.Pitch.Augmentable+import           Music.Pitch.Literal+import           Music.Score.Articulation+import           Music.Score.Color+import           Music.Score.Dynamics+import           Music.Score.Harmonics+import           Music.Score.Meta+import           Music.Score.Part+import           Music.Score.Pitch+import           Music.Score.Slide+import           Music.Score.Text+import           Music.Score.Ties+import           Music.Score.Tremolo+import           Music.Time++-- -------------------------------------------------------------------------------------+--+-- instance Semigroup a => Semigroup (DynamicT a) where+--     DynamicT (d1, x1) <> DynamicT (d2, x2) = DynamicT (d1 <> d2, x1 <> x2)+instance Semigroup a => Semigroup (SlideT a) where+    (<>) = liftA2 (<>)+instance Semigroup a => Semigroup (TieT a) where+    TieT (t1, x1) <> TieT (t2, x2) = TieT (t1 <> t2, x1 <> x2)+    -- This instance is suspect: in general chord notes are not required to share ties,+    -- so this instance may be removed (provided that TieT is moved inside Chord for+    -- all Preludes). See #134+instance Semigroup a => Semigroup (HarmonicT a) where+    (<>) = liftA2 (<>)+instance Semigroup a => Semigroup (TextT a) where+    (<>) = liftA2 (<>)+instance Semigroup a => Semigroup (PartT n a) where+    PartT (v1,x1) <> PartT (v2,x2) = PartT (v1, x1 <> x2)+++-- -------------------------------------------------------------------------------------++--+-- Aspect instaces (Pitch, Dynamics and Articulation) for PartT needs to go here,+-- as the other aspects depends on partwise traversals etc+--++type instance Pitch (PartT p a) = Pitch a+type instance SetPitch b (PartT p a) = PartT p (SetPitch b a)++instance HasPitch a b => HasPitch (PartT p a) (PartT p b) where+  pitch = _Wrapped . _2 . pitch+instance HasPitches a b => HasPitches (PartT p a) (PartT p b) where+  pitches = _Wrapped . _2 . pitches++type instance Pitch (DynamicT p a) = Pitch a+type instance SetPitch b (DynamicT p a) = DynamicT p (SetPitch b a)++instance HasPitch a b => HasPitch (DynamicT p a) (DynamicT p b) where+  pitch = _Wrapped . _2 . pitch+instance HasPitches a b => HasPitches (DynamicT p a) (DynamicT p b) where+  pitches = _Wrapped . _2 . pitches++type instance Pitch (ArticulationT p a) = Pitch a+type instance SetPitch b (ArticulationT p a) = ArticulationT p (SetPitch b a)++instance HasPitch a b => HasPitch (ArticulationT p a) (ArticulationT p b) where+  pitch = _Wrapped . _2 . pitch+instance HasPitches a b => HasPitches (ArticulationT p a) (ArticulationT p b) where+  pitches = _Wrapped . _2 . pitches++++type instance Dynamic (PartT p a) = Dynamic a+type instance SetDynamic b (PartT p a) = PartT p (SetDynamic b a)++instance HasDynamic a b => HasDynamic (PartT p a) (PartT p b) where+  dynamic = _Wrapped . _2 . dynamic+instance HasDynamics a b => HasDynamics (PartT p a) (PartT p b) where+  dynamics = _Wrapped . _2 . dynamics++type instance Dynamic (ArticulationT p a) = Dynamic a+type instance SetDynamic b (ArticulationT p a) = ArticulationT p (SetDynamic b a)++instance HasDynamic a b => HasDynamic (ArticulationT p a) (ArticulationT p b) where+  dynamic = _Wrapped . _2 . dynamic+instance HasDynamics a b => HasDynamics (ArticulationT p a) (ArticulationT p b) where+  dynamics = _Wrapped . _2 . dynamics++++type instance Articulation (PartT p a) = Articulation a+type instance SetArticulation b (PartT p a) = PartT p (SetArticulation b a)++instance HasArticulation a b => HasArticulation (PartT p a) (PartT p b) where+  articulation = _Wrapped . _2 . articulation+instance HasArticulations a b => HasArticulations (PartT p a) (PartT p b) where+  articulations = _Wrapped . _2 . articulations++-- TODO move up?+type instance Pitch (ColorT a)        = Pitch a+type instance SetPitch g (ColorT a)   = ColorT (SetPitch g a)+instance (HasPitches a b) => HasPitches (ColorT a) (ColorT b) where+  pitches = _Wrapped . pitches+instance (HasPitch a b) => HasPitch (ColorT a) (ColorT b) where+  pitch = _Wrapped . pitch++type instance Dynamic (ColorT a)        = Dynamic a+type instance SetDynamic g (ColorT a)   = ColorT (SetDynamic g a)+instance (HasDynamics a b) => HasDynamics (ColorT a) (ColorT b) where+  dynamics = _Wrapped . dynamics+instance (HasDynamic a b) => HasDynamic (ColorT a) (ColorT b) where+  dynamic = _Wrapped . dynamic++type instance Articulation (ColorT a)        = Articulation a+type instance SetArticulation g (ColorT a)   = ColorT (SetArticulation g a)+instance (HasArticulations a b) => HasArticulations (ColorT a) (ColorT b) where+  articulations = _Wrapped . articulations+instance (HasArticulation a b) => HasArticulation (ColorT a) (ColorT b) where+  articulation = _Wrapped . articulation+++-- -------------------------------------------------------------------------------------++deriving instance HasTremolo a => HasTremolo (PartT n a)+deriving instance HasHarmonic a => HasHarmonic (PartT n a)+deriving instance HasSlide a => HasSlide (PartT n a)+deriving instance HasText a => HasText (PartT n a)+++deriving instance HasTremolo a => HasTremolo (TieT a)+deriving instance HasHarmonic a => HasHarmonic (TieT a)+deriving instance HasSlide a => HasSlide (TieT a)+deriving instance HasText a => HasText (TieT a)++++-- TextT++instance Tiable a => Tiable (TextT a) where+  isTieEndBeginning (TextT (Couple (_,a))) = isTieEndBeginning a+  toTied (TextT (Couple (n,a))) = (TextT (Couple (n,b)), TextT (Couple (mempty,c))) where (b,c) = toTied a+deriving instance HasTremolo a => HasTremolo (TextT a)+deriving instance HasHarmonic a => HasHarmonic (TextT a)+deriving instance HasSlide a => HasSlide (TextT a)+++-- HarmonicT++instance Tiable a => Tiable (HarmonicT a) where+  isTieEndBeginning (HarmonicT (Couple (_,a))) = isTieEndBeginning a+  -- toTied = unzipR . fmap toTied+  toTied (HarmonicT (Couple (n,a))) = (HarmonicT (Couple (n,b)), HarmonicT (Couple (mempty,c))) where (b,c) = toTied a+deriving instance HasTremolo a => HasTremolo (HarmonicT a)+deriving instance HasSlide a => HasSlide (HarmonicT a)+deriving instance HasText a => HasText (HarmonicT a)+++-- SlideT+++instance Tiable a => Tiable (SlideT a) where+  isTieEndBeginning (SlideT (Couple (_,a))) = isTieEndBeginning a+  toTied = unzipR . fmap toTied+deriving instance HasTremolo a => HasTremolo (SlideT a)+deriving instance HasHarmonic a => HasHarmonic (SlideT a)+deriving instance HasText a => HasText (SlideT a)+++++deriving instance IsPitch a => IsPitch (TextT a)+deriving instance IsDynamics a => IsDynamics (TextT a)+deriving instance IsPitch a => IsPitch (HarmonicT a)+deriving instance IsDynamics a => IsDynamics (HarmonicT a)+deriving instance IsPitch a => IsPitch (SlideT a)+deriving instance IsDynamics a => IsDynamics (SlideT a)++deriving instance IsPitch a => IsPitch (ColorT a)+deriving instance IsDynamics a => IsDynamics (ColorT a)+deriving instance Transformable a => Transformable (ColorT a)+deriving instance Reversible a => Reversible (ColorT a)+deriving instance Alterable a => Alterable (ColorT a)+deriving instance Augmentable a => Augmentable (ColorT a)+deriving instance HasTremolo a => HasTremolo (ColorT a)+deriving instance HasHarmonic a => HasHarmonic (ColorT a)+deriving instance HasSlide a => HasSlide (ColorT a)+deriving instance HasText a => HasText (ColorT a)++deriving instance Transformable a => Transformable (SlideT a)+deriving instance Transformable a => Transformable (HarmonicT a)+deriving instance Transformable a => Transformable (TextT a)++deriving instance Reversible a => Reversible (SlideT a)+deriving instance Reversible a => Reversible (HarmonicT a)+deriving instance Reversible a => Reversible (TextT a)++deriving instance Alterable a => Alterable (SlideT a)+deriving instance Alterable a => Alterable (HarmonicT a)+deriving instance Alterable a => Alterable (TextT a)++deriving instance Augmentable a => Augmentable (SlideT a)+deriving instance Augmentable a => Augmentable (HarmonicT a)+deriving instance Augmentable a => Augmentable (TextT a)++++-------------------------------------------------------------------------------------+-- Literal instances+-------------------------------------------------------------------------------------+++instance Alterable a => Alterable (Score a) where+    sharpen = fmap sharpen+    flatten = fmap flatten+deriving instance Alterable a => Alterable (TieT a)+deriving instance Alterable a => Alterable (PartT n a)+deriving instance Alterable a => Alterable (DynamicT n a)+deriving instance Alterable a => Alterable (ArticulationT n a)++instance Augmentable a => Augmentable (Score a) where+    augment = fmap augment+    diminish = fmap diminish+deriving instance Augmentable a => Augmentable (TieT a)+deriving instance Augmentable a => Augmentable (PartT n a)+deriving instance Augmentable a => Augmentable (DynamicT n a)+deriving instance Augmentable a => Augmentable (ArticulationT n a)+++-- -------------------------------------------------------------------------------------+-- -- Num, Integral, Enum and Bounded+-- -------------------------------------------------------------------------------------+--+-- PartT++instance (Enum v, Eq v, Num a) => Num (PartT v a) where+    PartT (v,a) + PartT (_,b) = PartT (v,a+b)+    PartT (v,a) * PartT (_,b) = PartT (v,a*b)+    PartT (v,a) - PartT (_,b) = PartT (v,a-b)+    abs (PartT (v,a))          = PartT (v,abs a)+    signum (PartT (v,a))       = PartT (v,signum a)+    fromInteger a               = PartT (toEnum 0,fromInteger a)++instance (Enum v, Enum a) => Enum (PartT v a) where+    toEnum a = PartT (toEnum 0, toEnum a) -- TODO use def, mempty or minBound?+    fromEnum (PartT (v,a)) = fromEnum a++instance (Enum v, Bounded a) => Bounded (PartT v a) where+    minBound = PartT (toEnum 0, minBound)+    maxBound = PartT (toEnum 0, maxBound)++instance (Enum v, Ord v, Num a, Ord a, Real a) => Real (PartT v a) where+    toRational (PartT (v,a)) = toRational a++instance (Enum v, Ord v, Real a, Enum a, Integral a) => Integral (PartT v a) where+    PartT (v,a) `quotRem` PartT (_,b) = (PartT (v,q), PartT (v,r)) where (q,r) = a `quotRem` b+    toInteger (PartT (v,a)) = toInteger a++--+-- TODO suspect instances+-- We should remove both these after replacing [] by Chord in Preludes+--+instance Enum a => Enum [a] where+    toEnum a       = [toEnum a]+    fromEnum ([a]) = fromEnum a++instance Bounded a => Bounded [a] where+    minBound = [minBound]+    maxBound = [maxBound]+++-- TODO use wrapper type and replace withContext+type instance Dynamic (a,b,c) = (a,b,c)+type instance SetDynamic g (a,b,c) = g++instance Transformable a => Transformable (Maybe a) where+  transform s = fmap (transform s)+instance (Transformable a, Transformable b, Transformable c) => Transformable (a,b,c) where+  transform s (a,b,c) = (transform s a,transform s b,transform s c)++-- TODO place for this?+-- For use with single-note scores etc+instance Tiable a => Tiable (Score a) where+  beginTie = fmap beginTie+  endTie   = fmap endTie++instance Transformable a => Transformable (Ctxt a) where+  transform s = fmap (transform s)++instance Transformable a => Transformable (Average a) where+  transform s = fmap (transform s)++instance IsPitch a => IsPitch (Average a) where+  fromPitch = pure . fromPitch++instance IsInterval a => IsInterval (Average a) where+  fromInterval = pure . fromInterval++instance IsDynamics a => IsDynamics (Average a) where+  fromDynamics = pure . fromDynamics++
src/Music/Score/Meta.hs view
@@ -27,10 +27,6 @@ module Music.Score.Meta (         module Music.Time.Meta, -        -- TODO move-        (</>),-        rcat,-         -- * Meta-events         addMetaNote,         fromMetaReactive,@@ -66,66 +62,54 @@ import qualified Data.Foldable          as Foldable import qualified Data.List              as List -infixr 6 </>+addMetaNote :: forall a b . (AttributeClass a, HasMeta b) => Event a -> b -> b+addMetaNote x = applyMeta $ wrapTMeta $ noteToReactive x +fromMetaReactive :: forall a b . AttributeClass b => Meta -> Reactive b+fromMetaReactive = fromMaybe mempty . unwrapMeta --- |--- Concatenate parts.----rcat :: (HasParts' a, Enum (Part a)) => [Score a] -> Score a-rcat = List.foldr (</>) mempty+metaAt :: AttributeClass b => Time -> Score a -> b+metaAt x = (`atTime` x) . runScoreMeta --- |--- Similar to '<>', but increases parts in the second part to prevent collision.----(</>) :: (HasParts' a, Enum (Part a)) => Score a -> Score a -> Score a-a </> b = a <> moveParts offset b-    where-        -- max voice in a + 1-        offset = succ $ maximum' 0 $ fmap fromEnum $ toListOf parts a+metaAtStart :: AttributeClass b => Score a -> b+metaAtStart x = _onset x `metaAt` x -        -- |-        -- Move down one voice (all parts).-        ---        moveParts :: (Integral b, HasParts' a, Enum (Part a)) => b -> Score a -> Score a-        moveParts x = parts %~ (successor x)+withMeta :: AttributeClass a => (a -> Score b -> Score b) -> Score b -> Score b+withMeta f x = let+    m = (view meta) x+    r = fromMetaReactive m+    in case splitReactive r of+        Left  a -> f a x+        Right ((a, t), bs, (u, c)) ->+            (meta .~) m+                $ mapBefore t (f a)+                $ (composed $ fmap (\(view (from event) -> (s, a)) -> mapDuring s $ f a) $ bs)+                $ mapAfter u (f c)+                $ x -        -- |-        -- Move top-part to the specific voice (other parts follow).-        ---        moveToPart :: (Enum b, HasParts' a, Enum (Part a)) => b -> Score a -> Score a-        moveToPart v = moveParts (fromEnum v)+withMetaAtStart :: AttributeClass a => (a -> Score b -> Score b) -> Score b -> Score b+withMetaAtStart f x = let+    m = view meta x+    in f (fromMetaReactive m `atTime` _onset x) x  -        iterating :: (a -> a) -> (a -> a) -> Int -> a -> a-        iterating f g n-            | n <  0 = f . iterating f g (n + 1)-            | n == 0 = id-            | n >  0 = g . iterating f g (n - 1) -        successor :: (Integral b, Enum a) => b -> a -> a-        successor n = iterating pred succ (fromIntegral n) -        maximum' :: (Ord a, Foldable t) => a -> t a -> a-        maximum' z = option z getMax . foldMap (Option . Just . Max)   -addMetaNote :: forall a b . (AttributeClass a, HasMeta b) => Note a -> b -> b-addMetaNote x = applyMeta $ wrapTMeta $ noteToReactive x -fromMetaReactive :: forall a b . AttributeClass b => Meta -> Reactive b-fromMetaReactive = fromMaybe mempty . unwrapMeta   +-- JUNK+ withSpan :: Score a -> Score (Span, a)-withSpan = mapEvents (\t d x -> (t >-> d,x))-withTime = mapEvents (\t d x -> (t, x))+withSpan = mapTriples (\t d x -> (t >-> d,x))+withTime = mapTriples (\t d x -> (t, x))  inSpan t' (view range -> (t,u)) = t <= t' && t' < u --- TODO clean mapBefore :: Time -> (Score a -> Score a) -> Score a -> Score a mapDuring :: Span -> (Score a -> Score a) -> Score a -> Score a mapAfter :: Time -> (Score a -> Score a) -> Score a -> Score a@@ -137,46 +121,14 @@ -- Transform the score with the current value of some meta-information -- Each "update chunk" of the meta-info is processed separately ---- INTERNAL runScoreMeta :: forall a b . AttributeClass b => Score a -> Reactive b runScoreMeta = fromMetaReactive . (view meta) --- EXT-metaAt :: AttributeClass b => Time -> Score a -> b-metaAt x = (`atTime` x) . runScoreMeta---- EXT-metaAtStart :: AttributeClass b => Score a -> b-metaAtStart x = _onset x `metaAt` x--withMeta :: AttributeClass a => (a -> Score b -> Score b) -> Score b -> Score b-withMeta f x = let-    m = (view meta) x-    r = fromMetaReactive m-    in case splitReactive r of-        Left  a -> f a x-        Right ((a, t), bs, (u, c)) ->-            (meta .~) m-                $ mapBefore t (f a)-                $ (composed $ fmap (\(view (from note) -> (s, a)) -> mapDuring s $ f a) $ bs)-                $ mapAfter u (f c)-                $ x--withMetaAtStart :: AttributeClass a => (a -> Score b -> Score b) -> Score b -> Score b-withMetaAtStart f x = let-    m = view meta x-    in f (fromMetaReactive m `atTime` _onset x) x----    -- JUNK--- TODO move-noteToReactive :: Monoid a => Note a -> Reactive a+noteToReactive :: Monoid a => Event a -> Reactive a noteToReactive n = (pure <$> n) `activate` pure mempty -activate :: Note (Reactive a) -> Reactive a -> Reactive a-activate (view (from note) -> (view range -> (start,stop), x)) y = y `turnOn` (x `turnOff` y)+activate :: Event (Reactive a) -> Reactive a -> Reactive a+activate (view (from event) -> (view range -> (start,stop), x)) y = y `turnOn` (x `turnOff` y)     where         turnOn  = switchR start         turnOff = switchR stop
src/Music/Score/Meta/Attribution.hs view
@@ -118,15 +118,15 @@  -- | Set the given attribution in the given score. attribute :: (HasMeta a, HasPosition a) => Attribution -> a -> a-attribute a x = attributeDuring (_getEra x) a x+attribute a x = attributeDuring (_era x) a x  -- | Set the given attribution in the given part of a score. attributeDuring :: (HasMeta a) => Span -> Attribution -> a -> a-attributeDuring s a = addMetaNote (view note (s, a))+attributeDuring s a = addMetaNote (view event (s, a))  -- | Set composer of the given score. composer :: (HasMeta a, HasPosition a) => String -> a -> a-composer t x = composerDuring (_getEra x) t x+composer t x = composerDuring (_era x) t x  -- | Set composer of the given part of a score. composerDuring :: HasMeta a => Span -> String -> a -> a@@ -134,7 +134,7 @@  -- | Set lyricist of the given score. lyricist :: (HasMeta a, HasPosition a) => String -> a -> a-lyricist t x = lyricistDuring (_getEra x) t x+lyricist t x = lyricistDuring (_era x) t x  -- | Set lyricist of the given part of a score. lyricistDuring :: HasMeta a => Span -> String -> a -> a@@ -142,7 +142,7 @@  -- | Set arranger of the given score. arranger :: (HasMeta a, HasPosition a) => String -> a -> a-arranger t x = arrangerDuring (_getEra x) t x+arranger t x = arrangerDuring (_era x) t x  -- | Set arranger of the given part of a score. arrangerDuring :: HasMeta a => Span -> String -> a -> a
src/Music/Score/Meta/Barline.hs view
@@ -81,7 +81,7 @@  -- | Add a barline over the whole score. barline :: (HasMeta a, HasPosition a) => Barline -> a -> a-barline c x = barlineDuring (_getEra x) c x+barline c x = barlineDuring (_era x) c x  -- | Add a barline over the whole score. doubleBarline :: (HasMeta a, HasPosition a) => Barline -> a -> a@@ -93,7 +93,7 @@  -- | Add a barline to the given score. barlineDuring :: HasMeta a => Span -> Barline -> a -> a-barlineDuring s c = addMetaNote $ view note (s, (Option $ Just $ Last c))+barlineDuring s c = addMetaNote $ view event (s, (Option $ Just $ Last c))  -- | Extract barlines in from the given score, using the given default barline. withBarline :: (Barline -> Score a -> Score a) -> Score a -> Score a
src/Music/Score/Meta/Clef.hs view
@@ -68,13 +68,19 @@ data Clef = GClef | CClef | FClef     deriving (Eq, Ord, Show, Typeable) +instance IsPitch Clef where+  fromPitch l+    | l == c    = CClef+    | l == f    = FClef+    | otherwise = GClef+ -- | Set clef of the given score. clef :: (HasMeta a, HasPosition a) => Clef -> a -> a-clef c x = clefDuring (_getEra x) c x+clef c x = clefDuring (_era x) c x  -- | Set clef of the given part of a score. clefDuring :: HasMeta a => Span -> Clef -> a -> a-clefDuring s c = addMetaNote $ view note (s, (Option $ Just $ Last c))+clefDuring s c = addMetaNote $ view event (s, (Option $ Just $ Last c))  -- | Extract the clef in from the given score, using the given default clef. withClef :: Clef -> (Clef -> Score a -> Score a) -> Score a -> Score a
src/Music/Score/Meta/Fermata.hs view
@@ -77,11 +77,11 @@  -- | Add a fermata over the whole score. fermata :: (HasMeta a, HasPosition a) => Fermata -> a -> a-fermata c x = fermataDuring (_getEra x) c x+fermata c x = fermataDuring (_era x) c x  -- | Add a fermata to the given score. fermataDuring :: HasMeta a => Span -> Fermata -> a -> a-fermataDuring s c = addMetaNote $ view note (s, (Option $ Just $ Last c))+fermataDuring s c = addMetaNote $ view event (s, (Option $ Just $ Last c))  -- | Extract fermatas in from the given score, using the given default fermata. withFermata :: (Fermata -> Score a -> Score a) -> Score a -> Score a
src/Music/Score/Meta/Key.hs view
@@ -119,11 +119,11 @@  -- | Set the key signature of the given score. keySignature :: (HasMeta a, HasPosition a) => KeySignature -> a -> a-keySignature c x = keySignatureDuring (_getEra x) c x+keySignature c x = keySignatureDuring (_era x) c x  -- | Set the key signature of the given part of a score. keySignatureDuring :: HasMeta a => Span -> KeySignature -> a -> a-keySignatureDuring s c = addMetaNote $ view note (s, (Option $ Just $ Last c))+keySignatureDuring s c = addMetaNote $ view event (s, (Option $ Just $ Last c))  -- | Extract all key signatures from the given score, using the given default key signature. withKeySignature :: KeySignature -> (KeySignature -> Score a -> Score a) -> Score a -> Score a
src/Music/Score/Meta/Pickup.hs view
@@ -88,10 +88,10 @@ -- metronome noteVal bpm = Tempo Nothing (Just noteVal) $ 60 / (bpm * noteVal)  rehearsalMark :: (HasMeta a, HasPosition a) => Pickup -> a -> a-rehearsalMark c x = rehearsalMarkDuring (_getEra x) c x+rehearsalMark c x = rehearsalMarkDuring (_era x) c x  rehearsalMarkDuring :: HasMeta a => Span -> Pickup -> a -> a-rehearsalMarkDuring s x = addMetaNote $ view note (s, x)+rehearsalMarkDuring s x = addMetaNote $ view event (s, x)  withPickup :: (Pickup -> Score a -> Score a) -> Score a -> Score a withPickup = withMeta
src/Music/Score/Meta/RehearsalMark.hs view
@@ -92,10 +92,10 @@ -- metronome noteVal bpm = Tempo Nothing (Just noteVal) $ 60 / (bpm * noteVal)  rehearsalMark :: (HasMeta a, HasPosition a) => RehearsalMark -> a -> a-rehearsalMark c x = rehearsalMarkDuring (_getEra x) c x+rehearsalMark c x = rehearsalMarkDuring (_era x) c x  rehearsalMarkDuring :: HasMeta a => Span -> RehearsalMark -> a -> a-rehearsalMarkDuring s x = addMetaNote $ view note (s, x)+rehearsalMarkDuring s x = addMetaNote $ view event (s, x)  withRehearsalMark :: (RehearsalMark -> Score a -> Score a) -> Score a -> Score a withRehearsalMark = withMeta
src/Music/Score/Meta/Tempo.hs view
@@ -110,9 +110,11 @@ instance Show Tempo where     show (getTempo -> (nv, bpm)) = "metronome " ++ showR nv ++ " " ++ showR bpm         where-            showR (realToFrac -> (unRatio -> (x, 1))) = show x-            showR (realToFrac -> (unRatio -> (x, y))) = "(" ++ show x ++ "/" ++ show y ++ ")" +showR = showR' . realToFrac+showR' ((unRatio -> (x, 1))) = show x+showR' ((unRatio -> (x, y))) = "(" ++ show x ++ "/" ++ show y ++ ")"+ instance Default Tempo where     def = mempty @@ -176,11 +178,11 @@  -- | Set the tempo of the given score. tempo :: (HasMeta a, HasPosition a) => Tempo -> a -> a-tempo c x = tempoDuring (_getEra x) c x+tempo c x = tempoDuring (_era x) c x  -- | Set the tempo of the given part of a score. tempoDuring :: HasMeta a => Span -> Tempo -> a -> a-tempoDuring s c = addMetaNote $ view note (s, c)+tempoDuring s c = addMetaNote $ view event (s, c)   -- TODO move@@ -219,14 +221,14 @@  renderTempo sc =     flip composed sc $ fmap renderTempoScore-        $ tempoRegions (_getEra sc)-        $ tempoRegions0 (_getEra sc)+        $ tempoRegions (_era sc)+        $ tempoRegions0 (_era sc)         $ getTempoChanges defTempo sc  renderTempoTest :: Score a -> [TempoRegion] renderTempoTest sc = id-    $ tempoRegions (_getEra sc)-    $ tempoRegions0 (_getEra sc)+    $ tempoRegions (_era sc)+    $ tempoRegions0 (_era sc)     $ getTempoChanges defTempo sc  @@ -319,16 +321,23 @@  -} -presto     = metronome (1/4) 125-allegro    = metronome (1/4) 115-allegretto = metronome (1/4) 105-moderato   = metronome (1/4) 95-andante    = metronome (1/4) 85-adagio     = metronome (1/4) 65-largo      = metronome (1/4) 55-lento      = metronome (1/4) 45-+-- presto     = metronome (1/4) 125+-- allegro    = metronome (1/4) 115+-- allegretto = metronome (1/4) 105+-- moderato   = metronome (1/4) 95+-- andante    = metronome (1/4) 85+-- adagio     = metronome (1/4) 65+-- largo      = metronome (1/4) 55+-- lento      = metronome (1/4) 45 +presto      = metronome (1/4) 140+allegro     = metronome (1/4) 128+allegretto  = metronome (1/4) 118+moderato    = metronome (1/4) 98+andante     = metronome (1/4) 84+adagio      = metronome (1/4) 64+largo       = metronome (1/4) 48+lento       = metronome (1/4) 42  -- TODO consolidate -- optionFirst = Option . Just . First
src/Music/Score/Meta/Time.hs view
@@ -171,7 +171,7 @@  -- | Set the time signature of the given part of a score. timeSignatureDuring :: HasMeta a => Span -> TimeSignature -> a -> a-timeSignatureDuring s c = addMetaNote $ view note (s, optionFirst c)+timeSignatureDuring s c = addMetaNote $ view event (s, optionFirst c)  getTimeSignatures :: TimeSignature -> Score a -> Reactive TimeSignature getTimeSignatures def = fmap (fromMaybe def . unOptionFirst) . fromMetaReactive . (view meta)
src/Music/Score/Meta/Title.hs view
@@ -120,27 +120,27 @@  -- | Set title of the given score. title :: (HasMeta a, HasPosition a) => Title -> a -> a-title t x = titleDuring (_getEra x) t x+title t x = titleDuring (_era x) t x  -- | Set title of the given part of a score. titleDuring :: HasMeta a => Span -> Title -> a -> a-titleDuring s t = addMetaNote $ view note (s, t)+titleDuring s t = addMetaNote $ view event (s, t)  -- | Set subtitle of the given score. subtitle :: (HasMeta a, HasPosition a) => Title -> a -> a-subtitle t x = subtitleDuring (_getEra x) t x+subtitle t x = subtitleDuring (_era x) t x  -- | Set subtitle of the given part of a score. subtitleDuring :: HasMeta a => Span -> Title -> a -> a-subtitleDuring s t = addMetaNote $ view note (s, denoteTitle t)+subtitleDuring s t = addMetaNote $ view event (s, denoteTitle t)  -- | Set subsubtitle of the given score. subsubtitle :: (HasMeta a, HasPosition a) => Title -> a -> a-subsubtitle t x = subsubtitleDuring (_getEra x) t x+subsubtitle t x = subsubtitleDuring (_era x) t x  -- | Set subsubtitle of the given part of a score. subsubtitleDuring :: HasMeta a => Span -> Title -> a -> a-subsubtitleDuring s t = addMetaNote $ view note (s, denoteTitle (denoteTitle t))+subsubtitleDuring s t = addMetaNote $ view event (s, denoteTitle (denoteTitle t))  -- | Extract the title in from the given score. withTitle :: (Title -> Score a -> Score a) -> Score a -> Score a
src/Music/Score/Part.hs view
@@ -64,6 +64,9 @@         -- HasPart',         -- PartT(..),         -- getParts,+        +        (</>),+        rcat,   ) where  import           Control.Applicative@@ -201,14 +204,14 @@   parts = traverse . parts  -type instance Part (Note a) = Part a-type instance SetPart g (Note a) = Note (SetPart g a)+type instance Part (Event a) = Part a+type instance SetPart g (Event a) = Event (SetPart g a) -instance (HasPart a b) => HasPart (Note a) (Note b) where-  part = _Wrapped . whilstL part+instance (HasPart a b) => HasPart (Event a) (Event b) where+  part = from event . whilstL part -instance (HasParts a b) => HasParts (Note a) (Note b) where-  parts = _Wrapped . whilstL parts+instance (HasParts a b) => HasParts (Event a) (Event b) where+  parts = from event . whilstL parts  -- | -- List all the parts@@ -282,6 +285,7 @@   rev = fmap rev  instance Tiable a => Tiable (PartT n a) where+  isTieEndBeginning (PartT (_,a)) = isTieEndBeginning a   toTied (PartT (v,a)) = (PartT (v,b), PartT (v,c)) where (b,c) = toTied a  @@ -309,7 +313,7 @@     _Wrapped . _2   -- into NScore     . _Wrapped     . traverse-    . _Wrapped      -- this needed?+    . from event    -- this needed?     . whilstL parts  type instance Part (Voice a) = Part a@@ -322,4 +326,47 @@     . _Wrapped      -- this needed?     . whilstLD parts ++infixr 6 </>+++-- |+-- Concatenate parts.+--+rcat :: (HasParts' a, Enum (Part a)) => [Score a] -> Score a+rcat = List.foldr (</>) mempty++-- |+-- Similar to '<>', but increases parts in the second part to prevent collision.+--+(</>) :: (HasParts' a, Enum (Part a)) => Score a -> Score a -> Score a+a </> b = a <> moveParts offset b+    where+        -- max voice in a + 1+        offset = succ $ maximum' 0 $ fmap fromEnum $ toListOf parts a++        -- |+        -- Move down one voice (all parts).+        --+        moveParts :: (Integral b, HasParts' a, Enum (Part a)) => b -> Score a -> Score a+        moveParts x = parts %~ (successor x)++        -- |+        -- Move top-part to the specific voice (other parts follow).+        --+        moveToPart :: (Enum b, HasParts' a, Enum (Part a)) => b -> Score a -> Score a+        moveToPart v = moveParts (fromEnum v)+++        iterating :: (a -> a) -> (a -> a) -> Int -> a -> a+        iterating f g n+            | n <  0 = f . iterating f g (n + 1)+            | n == 0 = id+            | n >  0 = g . iterating f g (n - 1)++        successor :: (Integral b, Enum a) => b -> a -> a+        successor n = iterating pred succ (fromIntegral n)++        maximum' :: (Ord a, Foldable t) => a -> t a -> a+        maximum' z = option z getMax . foldMap (Option . Just . Max) 
src/Music/Score/Phrases.hs view
@@ -180,12 +180,12 @@     mvoiceToPVoice :: MVoice a -> PVoice a     mvoiceToPVoice =       map ( bimap voiceToRest voiceToPhrase-          . bimap (^.from unsafeEventsV) (^.from unsafeEventsV) )+          . bimap (^.from unsafePairs) (^.from unsafePairs) )        . groupDiff' (isJust . snd)-       . view eventsV+       . view pairs      voiceToRest :: MVoice a -> Duration-    voiceToRest = sumOf (eventsV.each._1) . fmap (\x -> assert (isNothing x) x)+    voiceToRest = sumOf (pairs.each._1) . fmap (\x -> assert (isNothing x) x)     -- TODO just _duration      voiceToPhrase :: MVoice a -> Phrase a@@ -206,11 +206,11 @@ singleMVoice = iso scoreToVoice voiceToScore'   where     scoreToVoice :: {-Transformable a =>-} Score a -> MVoice a-    scoreToVoice = (^. voice) . fmap (^. stretched) . fmap throwTime . addRests .+    scoreToVoice = (^. voice) . fmap (^. note) . fmap throwTime . addRests .       -- TODO       List.sortBy (comparing (^._1))       -- end TODO-      . (^. events)+      . (^. triples)       where         throwTime (t,d,x) = (d,x)         addRests = concat . snd . List.mapAccumL g 0@@ -221,7 +221,7 @@               | otherwise = error "singleMVoice: Strange prevTime"      voiceToScore :: Voice a -> Score a-    voiceToScore = scat . fmap g . (^. stretcheds) where g = (^. stretchedValue) . fmap return+    voiceToScore = renderAlignedVoice . aligned 0 0      voiceToScore' :: MVoice a -> Score a     voiceToScore' = mcatMaybes . voiceToScore@@ -232,7 +232,10 @@ mapPhrasesWithPrevAndCurrentOnset f = over (mvoices . mVoiceTVoice) (withPrevAndCurrentOnset f)  withPrevAndCurrentOnset :: (Maybe Time -> Time -> a -> b) -> Track a -> Track b-withPrevAndCurrentOnset f = over delayeds (fmap (\(x,y,z) -> fmap (f (fmap _onset x) (_onset y)) y) . withPrevNext)+withPrevAndCurrentOnset f = over placeds (fmap (\(x,y,z) -> fmap (f (fmap placedOnset x) (placedOnset y)) y) . withPrevNext)+  where+    placedOnset :: Placed a -> Time+    placedOnset = view (from placed . _1)  mVoiceTVoice :: Lens (MVoice a) (MVoice b) (TVoice a) (TVoice b) mVoiceTVoice = mVoicePVoice . pVoiceTVoice@@ -269,7 +272,7 @@ firsts f = uncurry zip . first f . unzipR  mkTrack :: [(Time, a)] -> Track a-mkTrack = view track . map (view delayed)+mkTrack = view track . map (view placed)  withDurationR :: (Functor f, HasDuration a) => f a -> f (Duration, a) withDurationR = fmap $ \x -> (_duration x, x)
src/Music/Score/Pitch.hs view
@@ -105,6 +105,12 @@ import           Data.Traversable              (Traversable) import           Data.Typeable import           Data.VectorSpace              hiding (Sum)+import           Data.Set                      (Set)+import           Data.Map                      (Map)+import           Data.Sequence                 (Seq)+import qualified Data.Set as Set+import qualified Data.Map as Map+import qualified Data.Sequence as Seq  import           Music.Pitch.Literal import           Music.Score.Harmonics@@ -112,7 +118,6 @@ import           Music.Score.Slide import           Music.Score.Text import           Music.Score.Ties--- import           Music.Score.Tremolo import           Music.Score.Phrases import           Music.Time import           Music.Time.Internal.Transform@@ -125,7 +130,7 @@ -- @ -- 'Pitch' (c,a)             ~ 'Pitch' a -- 'Pitch' [a]               ~ 'Pitch' a--- 'Pitch' ('Note' a)          ~ 'Pitch' a+-- 'Pitch' ('Event' a)          ~ 'Pitch' a -- 'Pitch' ('Voice' a)         ~ 'Pitch' a -- 'Pitch' ('Score' a)         ~ 'Pitch' a -- @@@ -151,7 +156,7 @@ -- @ -- 'SetPitch' b (c,a)          ~ (c, 'SetPitch' b a) -- 'SetPitch' b [a]            ~ ['SetPitch' b a]--- 'SetPitch' g ('Note' a)       ~ Note ('SetPitch' g a)+-- 'SetPitch' g ('Event' a)       ~ Event ('SetPitch' g a) -- 'SetPitch' g ('Voice' a)      ~ 'Voice' ('SetPitch' g a) -- 'SetPitch' g ('Score' a)      ~ 'Score' ('SetPitch' g a) -- @@@ -265,50 +270,61 @@ PRIM_PITCH_INSTANCE(Double)  -type instance Pitch (c,a)               = Pitch a-type instance SetPitch b (c,a)          = (c,SetPitch b a)-type instance Pitch [a]                 = Pitch a-type instance SetPitch b [a]            = [SetPitch b a]+type instance Pitch (c,a)                 = Pitch a+type instance SetPitch b (c,a)            = (c,SetPitch b a)+type instance Pitch [a]                   = Pitch a+type instance SetPitch b [a]              = [SetPitch b a]+type instance Pitch (Map k a)             = Pitch a+type instance SetPitch b (Map k a)        = Map k (SetPitch b a)+type instance Pitch (Seq a)               = Pitch a+type instance SetPitch b (Seq a)          = Seq (SetPitch b a) -type instance Pitch (Maybe a)           = Pitch a-type instance SetPitch b (Maybe a)      = Maybe (SetPitch b a)-type instance Pitch (Either c a)        = Pitch a-type instance SetPitch b (Either c a)   = Either c (SetPitch b a)+type instance Pitch (Maybe a)             = Pitch a+type instance SetPitch b (Maybe a)        = Maybe (SetPitch b a)+type instance Pitch (Either c a)          = Pitch a+type instance SetPitch b (Either c a)     = Either c (SetPitch b a) -type instance Pitch (Note a)            = Pitch a-type instance SetPitch b (Note a)       = Note (SetPitch b a)-type instance Pitch (Delayed a)         = Pitch a-type instance SetPitch b (Delayed a)    = Delayed (SetPitch b a)-type instance Pitch (Stretched a)       = Pitch a-type instance SetPitch b (Stretched a)  = Stretched (SetPitch b a)+type instance Pitch (Event a)             = Pitch a+type instance SetPitch b (Event a)        = Event (SetPitch b a)+type instance Pitch (Placed a)            = Pitch a+type instance SetPitch b (Placed a)       = Placed (SetPitch b a)+type instance Pitch (Note a)              = Pitch a+type instance SetPitch b (Note a)         = Note (SetPitch b a) -type instance Pitch (Voice a)       = Pitch a-type instance SetPitch b (Voice a)  = Voice (SetPitch b a)-type instance Pitch (Chord a)       = Pitch a-type instance SetPitch b (Chord a)  = Chord (SetPitch b a)-type instance Pitch (Track a)       = Pitch a-type instance SetPitch b (Track a)  = Track (SetPitch b a)-type instance Pitch (Score a)       = Pitch a-type instance SetPitch b (Score a)  = Score (SetPitch b a)+type instance Pitch (Voice a)             = Pitch a+type instance SetPitch b (Voice a)        = Voice (SetPitch b a)+type instance Pitch (Track a)             = Pitch a+type instance SetPitch b (Track a)        = Track (SetPitch b a)+type instance Pitch (Score a)             = Pitch a+type instance SetPitch b (Score a)        = Score (SetPitch b a)  instance HasPitch a b => HasPitch (c, a) (c, b) where   pitch = _2 . pitch instance HasPitches a b => HasPitches (c, a) (c, b) where   pitches = traverse . pitches -instance (HasPitches a b) => HasPitches (Note a) (Note b) where-  pitches = _Wrapped . whilstL pitches-instance (HasPitch a b) => HasPitch (Note a) (Note b) where-  pitch = _Wrapped . whilstL pitch+instance HasPitches a b => HasPitches [a] [b] where+  pitches = traverse . pitches -instance (HasPitches a b) => HasPitches (Delayed a) (Delayed b) where+instance HasPitches a b => HasPitches (Seq a) (Seq b) where+  pitches = traverse . pitches++instance HasPitches a b => HasPitches (Map k a) (Map k b) where+  pitches = traverse . pitches++instance (HasPitches a b) => HasPitches (Event a) (Event b) where+  pitches = from event . whilstL pitches+instance (HasPitch a b) => HasPitch (Event a) (Event b) where+  pitch = from event . whilstL pitch++instance (HasPitches a b) => HasPitches (Placed a) (Placed b) where   pitches = _Wrapped . whilstLT pitches-instance (HasPitch a b) => HasPitch (Delayed a) (Delayed b) where+instance (HasPitch a b) => HasPitch (Placed a) (Placed b) where   pitch = _Wrapped . whilstLT pitch -instance (HasPitches a b) => HasPitches (Stretched a) (Stretched b) where+instance (HasPitches a b) => HasPitches (Note a) (Note b) where   pitches = _Wrapped . whilstLD pitches-instance (HasPitch a b) => HasPitch (Stretched a) (Stretched b) where+instance (HasPitch a b) => HasPitch (Note a) (Note b) where   pitch = _Wrapped . whilstLD pitch  instance HasPitches a b => HasPitches (Maybe a) (Maybe b) where@@ -317,24 +333,25 @@ instance HasPitches a b => HasPitches (Either c a) (Either c b) where   pitches = traverse . pitches -instance HasPitches a b => HasPitches [a] [b] where-  pitches = traverse . pitches- instance HasPitches a b => HasPitches (Voice a) (Voice b) where   pitches = traverse . pitches  instance HasPitches a b => HasPitches (Track a) (Track b) where   pitches = traverse . pitches +{-+type instance Pitch (Chord a)       = Pitch a+type instance SetPitch b (Chord a)  = Chord (SetPitch b a) instance HasPitches a b => HasPitches (Chord a) (Chord b) where   pitches = traverse . pitches+-}  instance (HasPitches a b) => HasPitches (Score a) (Score b) where   pitches =     _Wrapped . _2   -- into NScore     . _Wrapped     . traverse-    . _Wrapped      -- this needed?+    . from event    -- this needed?     . whilstL pitches  
src/Music/Score/Slide.hs view
@@ -91,7 +91,7 @@   setEndGliss   n = fmap (setEndGliss n)   setEndSlide   n = fmap (setEndSlide n) -instance HasSlide a => HasSlide (Stretched a) where+instance HasSlide a => HasSlide (Note a) where   setBeginGliss n = fmap (setBeginGliss n)   setBeginSlide n = fmap (setBeginSlide n)   setEndGliss   n = fmap (setEndGliss n)
src/Music/Score/Text.hs view
@@ -74,7 +74,7 @@ instance HasText a => HasText [a] where   addText s = fmap (addText s) -instance HasText a => HasText (Stretched a) where+instance HasText a => HasText (Note a) where   addText s = fmap (addText s)  instance HasText a => HasText (Voice a) where
src/Music/Score/Ties.hs view
@@ -33,8 +33,8 @@         TieT(..),          -- * Splitting tied notes in scores-        -- splitTiesVoice,-        splitTiesVoiceAt,+        -- splitTies,+        splitTiesAt,    ) where @@ -54,7 +54,7 @@ import           Data.Semigroup import           Data.Typeable import           Data.Monoid.Average-import           Data.VectorSpace        hiding (Sum)+import           Data.VectorSpace        hiding (Sum, getSum)  import           Music.Dynamics.Literal import           Music.Pitch.Literal@@ -91,6 +91,14 @@   --   toTied    :: a -> (a, a)   toTied a = (beginTie a, endTie a)+  +  isTieEndBeginning :: a -> (Bool, Bool)+  +  isTieBeginning :: a -> Bool+  isTieBeginning = snd . isTieEndBeginning+  +  isTieEnd :: a -> Bool+  isTieEnd = fst . isTieEndBeginning   @@ -103,16 +111,17 @@  instance Rewrapped (TieT a) (TieT b) -instance Tiable Double      where { beginTie = id ; endTie = id }-instance Tiable Float       where { beginTie = id ; endTie = id }-instance Tiable Char        where { beginTie = id ; endTie = id }-instance Tiable Int         where { beginTie = id ; endTie = id }-instance Tiable Integer     where { beginTie = id ; endTie = id }-instance Tiable ()          where { beginTie = id ; endTie = id }-instance Tiable (Ratio a)   where { beginTie = id ; endTie = id }+instance Tiable Double      where { beginTie = id ; endTie = id ; isTieEndBeginning _ = (False, False) }+instance Tiable Float       where { beginTie = id ; endTie = id ; isTieEndBeginning _ = (False, False) }+instance Tiable Char        where { beginTie = id ; endTie = id ; isTieEndBeginning _ = (False, False) }+instance Tiable Int         where { beginTie = id ; endTie = id ; isTieEndBeginning _ = (False, False) }+instance Tiable Integer     where { beginTie = id ; endTie = id ; isTieEndBeginning _ = (False, False) }+instance Tiable ()          where { beginTie = id ; endTie = id ; isTieEndBeginning _ = (False, False) }+instance Tiable (Ratio a)   where { beginTie = id ; endTie = id ; isTieEndBeginning _ = (False, False) }  instance Tiable a => Tiable (TieT a) where-  toTied (TieT ((prevTie, nextTie), a))   = (TieT ((prevTie, Any True), b), TieT ((Any True, nextTie), c))+  isTieEndBeginning (TieT (ties, _)) = over both getAny $ ties+  toTied (TieT ((prevTie, nextTie), a)) = (TieT ((prevTie, Any True), b), TieT ((Any True, nextTie), c))        where (b,c) = toTied a  instance Tiable a => Tiable [a] where@@ -126,18 +135,23 @@ -- This restriction assures all chord notes are in the same part -- instance Tiable a => Tiable (c, a) where+  isTieEndBeginning = isTieEndBeginning . extract   toTied = unzipR . fmap toTied  instance Tiable a => Tiable (Maybe a) where+  isTieEndBeginning = maybe (False, False) isTieEndBeginning   toTied = unzipR . fmap toTied  instance Tiable a => Tiable (Average a) where+  isTieEndBeginning = isTieEndBeginning . getAverage   toTied = unzipR . fmap toTied  instance Tiable a => Tiable (Sum a) where+  isTieEndBeginning = isTieEndBeginning . getSum   toTied = unzipR . fmap toTied  instance Tiable a => Tiable (Product a) where+  isTieEndBeginning = isTieEndBeginning . getProduct   toTied = unzipR . fmap toTied  -- Lifted instances@@ -202,10 +216,10 @@ -- | -- Split all notes that cross a barlines into a pair of tied notes. ---splitTiesVoice :: Tiable a => Voice a -> Voice a-splitTiesVoice = (^. voice) . map (^. stretched)+splitTies :: Tiable a => Voice a -> Voice a+splitTies = (^. voice) . map (^. note)   . concat . snd . List.mapAccumL g 0-  . map (^. from stretched) . (^. stretcheds)+  . map (^. from note) . (^. notes)   where     g t (d, x) = (t + d, occs)       where@@ -218,20 +232,20 @@ -- Split all voice into bars, using the given bar durations. Music that does not -- fit into the given durations is discarded. ----- Notes that cross a barlines are split into tied notes.+-- Events that cross a barlines are split into tied notes. ---splitTiesVoiceAt :: Tiable a => [Duration] -> Voice a -> [Voice a]-splitTiesVoiceAt barDurs x = fmap ((^. voice) . map (^. stretched)) $ splitTiesVoiceAt' barDurs ((map (^. from stretched) . (^. stretcheds)) x)+splitTiesAt :: Tiable a => [Duration] -> Voice a -> [Voice a]+splitTiesAt barDurs x = fmap ((^. voice) . map (^. note)) $ splitTiesAt' barDurs ((map (^. from note) . (^. notes)) x) -splitTiesVoiceAt' :: Tiable a => [Duration] -> [(Duration, a)] -> [[(Duration, a)]]-splitTiesVoiceAt' []  _  =  []-splitTiesVoiceAt' _  []  =  []-splitTiesVoiceAt' (barDur : rbarDur) occs = case splitDurFor barDur occs of+splitTiesAt' :: Tiable a => [Duration] -> [(Duration, a)] -> [[(Duration, a)]]+splitTiesAt' []  _  =  []+splitTiesAt' _  []  =  []+splitTiesAt' (barDur : rbarDur) occs = case splitDurFor barDur occs of   (barOccs, [])       -> barOccs : []-  (barOccs, restOccs) -> barOccs : splitTiesVoiceAt' rbarDur restOccs+  (barOccs, restOccs) -> barOccs : splitTiesAt' rbarDur restOccs -tsplitTiesVoiceAt :: [Duration] -> [Duration] -> [[(Duration, Char)]]-tsplitTiesVoiceAt barDurs = fmap (map (^. from stretched) . (^. stretcheds)) . splitTiesVoiceAt barDurs . ((^. voice) . map (^. stretched)) . fmap (\x -> (x,'_'))+tsplitTiesAt :: [Duration] -> [Duration] -> [[(Duration, Char)]]+tsplitTiesAt barDurs = fmap (map (^. from note) . (^. notes)) . splitTiesAt barDurs . ((^. voice) . map (^. note)) . fmap (\x -> (x,'_'))  -- | -- Split an event into one chunk of the duration @s@, followed parts shorter than duration @t@.@@ -247,14 +261,14 @@   -- |--- Extract as many notes or parts of notes as possible in the given positive duration, and--- return it with remaining notes.+-- Extract as many events or parts of events as possible in the given positive duration, and+-- return it with remaining events. ----- The extracted notes always fit into the given duration, i.e.+-- The extracted events always fit into the given duration, i.e. -- -- > sum $ fmap duration $ fst $ splitDurFor maxDur xs <= maxDur ----- If there are remaining notes, they always fit exactly, i.e.+-- If there are remaining events, they always fit exactly, i.e. -- -- > sum $ fmap duration $ fst $ splitDurFor maxDur xs == maxDur  iff  (not $ null $ snd $ splitDurFor maxDur xs) --@@ -274,8 +288,8 @@   -- toTied _ = ('(',')')  -- |--- Split a note if it is longer than the given duration. Returns the first part of the--- note (which always <= s) and the rest.+-- Split a event if it is longer than the given duration. Returns the first part of the+-- event (which always <= s) and the rest. -- -- > splitDur maxDur (d,a) --
src/Music/Score/Tremolo.hs view
@@ -60,7 +60,6 @@ import           Music.Pitch.Augmentable import           Music.Pitch.Literal import           Music.Score.Articulation--- import           Music.Score.Color import           Music.Score.Dynamics import           Music.Score.Harmonics import           Music.Score.Meta@@ -103,6 +102,7 @@ deriving instance (Monoid b, Alterable a) => Alterable (Couple b a) deriving instance (Monoid b, Augmentable a) => Augmentable (Couple b a) instance Tiable a => Tiable (Couple b a) where+  isTieEndBeginning (Couple (_,a)) = isTieEndBeginning a   toTied = unzipR . fmap toTied  
src/Music/Time.hs view
@@ -12,13 +12,10 @@ -------------------------------------------------------------------------------------  module Music.Time (-        -- * Prerequisites     module Data.Functor.Rep.Lens, -    -- * Basic types     module Music.Time.Types, -    -- * Time transformations     module Music.Time.Transform,     module Music.Time.Duration,     module Music.Time.Position,@@ -26,25 +23,25 @@     module Music.Time.Reverse,     module Music.Time.Juxtapose,     module Music.Time.Rest,+    module Music.Time.Aligned, -    -- * Time types-    -- ** Discrete time-    module Music.Time.Stretched,-    module Music.Time.Delayed,+    module Music.Time.Placed,     module Music.Time.Note,-    module Music.Time.Future,-    module Music.Time.Past,-    module Music.Time.Nominal,-    module Music.Time.Graces,+    module Music.Time.Event,     module Music.Time.Voice,     module Music.Time.Chord,     module Music.Time.Track,     module Music.Time.Score, -    -- ** Continous time+    module Music.Time.Nominal,+    module Music.Time.Graces,++    module Music.Time.Future,+    module Music.Time.Past,+    module Music.Time.Reactive,+     module Music.Time.Segment,     module Music.Time.Behavior,-    module Music.Time.Reactive,   ) where  import           Data.Functor.Rep@@ -58,19 +55,19 @@ import           Music.Time.Split import           Music.Time.Transform import           Music.Time.Types+import           Music.Time.Aligned  import           Music.Time.Behavior import           Music.Time.Chord-import           Music.Time.Delayed-import           Music.Time.Note+import           Music.Time.Placed import           Music.Time.Future-import           Music.Time.Past-import           Music.Time.Nominal import           Music.Time.Graces+import           Music.Time.Nominal+import           Music.Time.Event+import           Music.Time.Past import           Music.Time.Reactive import           Music.Time.Score import           Music.Time.Segment-import           Music.Time.Stretched+import           Music.Time.Note import           Music.Time.Track import           Music.Time.Voice-
+ src/Music/Time/Aligned.hs view
@@ -0,0 +1,129 @@++{-# LANGUAGE DeriveDataTypeable         #-}+{-# LANGUAGE DeriveFoldable             #-}+{-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE DeriveTraversable          #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses      #-}+{-# LANGUAGE TypeFamilies               #-}+{-# LANGUAGE TypeOperators              #-}+{-# LANGUAGE RankNTypes                 #-}+{-# LANGUAGE TupleSections              #-}++-------------------------------------------------------------------------------------+-- |+-- Copyright   : (c) Hans Hoglund 2012-2014+--+-- License     : BSD-style+--+-- Maintainer  : hans@hanshoglund.se+-- Stability   : experimental+-- Portability : non-portable (TF,GNTD)+--+-------------------------------------------------------------------------------------++module Music.Time.Aligned (+      Aligned,+      aligned,+      renderAligned,+      renderAlignedVoice,+      renderAlignedNote,+      renderAlignedDuration,+  ) where++import           Control.Applicative+import           Control.Comonad+import           Control.Lens            hiding (Indexable, Level, above, below,+                                          index, inside, parts, reversed,+                                          transform, (<|), (|>))+import           Data.AffineSpace+import           Data.AffineSpace.Point+import           Data.Bifunctor+import           Data.Foldable           (Foldable)+import qualified Data.Foldable           as Foldable+import           Data.Functor.Adjunction (unzipR)+import           Data.Functor.Couple+import           Data.String+import           Data.Typeable+import           Data.VectorSpace++import           Music.Dynamics.Literal+import           Music.Pitch.Literal+import           Music.Time.Reverse+import           Music.Time.Juxtapose+import           Music.Time.Split+import           Music.Time.Note+import           Music.Time.Event+import           Music.Time.Voice+import           Music.Time.Score+++-- type AlignedVoice a = Aligned (Voice a)++-- | 'Aligned' places a vector-like object in space, by fixing a local duration interpolating+-- the vector to a specific point in time. The aligned value must be an instance of+-- 'HasDuration', with @'view' 'duration'@ providing the size of the vector.+--+-- This is analogous to alignment in a graphical program. To align something at onset, midpoint+-- or offset, use 0, 0.5 or 1 as the local duration value.+newtype Aligned v = Aligned { getAligned :: (Time, LocalDuration, v) }++-- | Align the given value so that its local duration occurs at the given time.+aligned :: Time -> LocalDuration -> v -> Aligned v+aligned t d a = Aligned (t, d, a)++instance Show a => Show (Aligned a) where+  show (Aligned (t,d,v)) = "aligned ("++show t++") ("++show d++") ("++ show v++")"++instance Transformable v => Transformable (Aligned v) where+  transform s (Aligned (t, d, v)) = Aligned (transform s t, d, transform s v)++instance HasDuration v => HasDuration (Aligned v) where+  _duration (Aligned (_, _, v)) = _duration v++instance HasDuration v => HasPosition (Aligned v) where+  -- _position (Aligned (position, alignment, v)) = alerp (position .-^ (size * alignment)) (position .+^ (size * (1-alignment)))+  --   where+  --     size = _duration v+  _era (Aligned (position, alignment, v)) = +    (position .-^ (size * alignment)) <-> (position .+^ (size * (1-alignment)))+    where+      size = _duration v++-- renderAligned :: AlignedVoice a -> Score a+renderAligned :: HasDuration a => (Span -> a -> b) -> Aligned a -> b+renderAligned f a@(Aligned (_, _, v)) = f (_era a) v+++++-- Somewhat suspect, see below for clarity...++voiceToScoreInEra :: Span -> Voice a -> Score a+voiceToScoreInEra e = set era e . scat . map (uncurry stretch) . view pairs . fmap pure++noteToEventInEra :: Span -> Note a -> Event a+noteToEventInEra e = set era e . view notee . fmap pure++durationToSpanInEra :: Span -> Duration -> Span+durationToSpanInEra = const++-- TODO compare placeAt etc.+++-- | Convert an aligned voice to a score.+renderAlignedVoice :: Aligned (Voice a) -> Score a+renderAlignedVoice = renderAligned voiceToScoreInEra++-- | Convert an aligned note to an event.+renderAlignedNote :: Aligned (Note a) -> Event a+renderAlignedNote = renderAligned noteToEventInEra++-- | Convert an aligned duration to a span.+renderAlignedDuration :: Aligned Duration -> Span+renderAlignedDuration = renderAligned durationToSpanInEra+++++
src/Music/Time/Behavior.hs view
@@ -1,18 +1,11 @@  {-# LANGUAGE ConstraintKinds            #-} {-# LANGUAGE DeriveDataTypeable         #-}-{-# LANGUAGE FlexibleContexts           #-}-{-# LANGUAGE FlexibleInstances          #-}-{-# LANGUAGE GADTs                      #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses      #-}-{-# LANGUAGE NoMonomorphismRestriction  #-}-{-# LANGUAGE RankNTypes                 #-}-{-# LANGUAGE ScopedTypeVariables        #-} {-# LANGUAGE StandaloneDeriving         #-} {-# LANGUAGE TupleSections              #-} {-# LANGUAGE TypeFamilies               #-}-{-# LANGUAGE UndecidableInstances       #-}  ------------------------------------------------------------------------------------- -- |@@ -81,7 +74,7 @@ import           Data.Typeable import           Music.Time.Bound import           Music.Time.Internal.Transform-import           Music.Time.Note+import           Music.Time.Event import           Music.Time.Reverse import           Music.Time.Score import           Music.Time.Split@@ -145,6 +138,11 @@ 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@@ -152,28 +150,21 @@  instance Reversible (Behavior a) where   rev = stretch (-1)-  -- TODO alternative+  -- Or: alternative   -- rev = (stretch (-1) `whilst` undelaying 0.5)   -- (i.e. revDefault pretending that Behaviors have era (0 <-> 1)) -instance Representable Behavior where-  type Rep Behavior = Time-  tabulate = Behavior-  index (Behavior x) = x- 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) --- TODO bad instance+-- TODO bad instance Real a => Real (Behavior a) where   toRational = toRational . (! 0) --- #ifdef INCLUDE_LIFTED-deriving instance AdditiveGroup a => AdditiveGroup (Behavior a)- instance IsString a => IsString (Behavior a) where   fromString = pure . fromString @@ -195,12 +186,15 @@   diminish = fmap diminish  instance Eq a => Eq (Behavior a) where-  (==) = error "No fun"+  (==) = error "No overloading for behavior: (<=)"  instance Ord a => Ord (Behavior a) where-  (<) = error "No fun"-  max = liftA2 max-  min = liftA2 min+  (<=) = 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@@ -214,7 +208,6 @@   type Diff (Behavior a) = Behavior (Diff a)   (.-.) = liftA2 (.-.)   (.+^) = liftA2 (.+^)--- #endif  -- | -- View a behavior as a time function and vice versa.@@ -240,22 +233,8 @@ unbehavior :: Iso (Behavior a) (Behavior b) (Time -> a) (Time -> b) unbehavior = from behavior ------ @--- ('const' x)^.'behavior' ! t = x   forall t--- @-------- -- |--- A behavior that----line' :: Behavior Time-line' = id ^. R.tabulated---- |--- A behavior that gives the current time, i.e. the identity function+-- A behavior that gives the current time. -- -- Should really have the type 'Behavior' 'Time', but is provided in a more general form -- for convenience.@@ -275,13 +254,12 @@ -- > f t | t < 0     = 0 -- >     | t > 1     = 1 -- >     | otherwise = t---  -- | -- A behavior that ---interval :: (Fractional a, Transformable a) => Time -> Time -> Note (Behavior a)-interval t u = (t <-> u, line) ^. note+interval :: (Fractional a, Transformable a) => Time -> Time -> Event (Behavior a)+interval t u = (t <-> u, line) ^. event  -- | -- A behavior that@@ -308,7 +286,6 @@ impulse = switch' 0 0 1 0 -- > f t | t == 0    = 1 -- >     | otherwise = 0---  -- | -- A behavior that goes from 0 to 1 at time 0.@@ -321,8 +298,6 @@ turnOff = switch 0 1 0  ----- TODO--- -- Because the 'Time' type is fixed and unbounded in the current version, we can not -- define a generix isomorphism from behaviors to segments. If we change the library to -- provide multiple time representations (using TFs or similar), we should provide@@ -331,27 +306,7 @@ -- > focusOnFullRange :: Bounded Time => Behavior a -> Segment a -- > focusingOnFullRange :: Bounded Time => Iso' (Behavior a) (Segment a) ----{- -- |--- View part of a 'Behavior' as a 'Segment'.------ This can be used to modify a behavior in a specific range, as in------ @--- 'line' & 'focusing' `on` (2 '<->' 3) '+a~' 1--- 'line' & 'focusingOn' (2 '<->' 3) '+~' 1--- @----focusingOn :: Span -> Lens' (Behavior a) (Segment a)-focusingOn s = flip whilstM (negateV s) . focusing--- or focusing . flip whilstM s--}---- focusing `on` s == focusingOn s-f `on` s = transformed (negateV s) . f---- | -- Instantly switch from one behavior to another. -- switch :: Time -> Behavior a -> Behavior a -> Behavior a@@ -374,10 +329,11 @@   EQ -> ry ! u   GT -> rz ! u --- TODO move++-- Internal++tau :: Floating a => a tau = 2 * pi  floor' :: RealFrac a => a -> a floor' = fromIntegral . floor---- JUNK
src/Music/Time/Bound.hs view
@@ -1,17 +1,11 @@  {-# LANGUAGE ConstraintKinds            #-} {-# LANGUAGE DeriveDataTypeable         #-}-{-# LANGUAGE DeriveFunctor              #-}-{-# LANGUAGE FlexibleContexts           #-}-{-# LANGUAGE FlexibleInstances          #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses      #-}-{-# LANGUAGE NoMonomorphismRestriction  #-}-{-# LANGUAGE RankNTypes                 #-}-{-# LANGUAGE ScopedTypeVariables        #-}+{-# LANGUAGE StandaloneDeriving         #-} {-# LANGUAGE TupleSections              #-} {-# LANGUAGE TypeFamilies               #-}-{-# LANGUAGE UndecidableInstances       #-} {-# LANGUAGE ViewPatterns               #-}  -------------------------------------------------------------------------------------
src/Music/Time/Chord.hs view
@@ -1,20 +1,15 @@ -{-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE ConstraintKinds            #-} {-# LANGUAGE DeriveDataTypeable         #-}-{-# LANGUAGE DeriveFoldable             #-} {-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE DeriveFoldable             #-} {-# LANGUAGE DeriveTraversable          #-}-{-# LANGUAGE FlexibleContexts           #-}-{-# LANGUAGE FlexibleInstances          #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses      #-}-{-# LANGUAGE NoMonomorphismRestriction  #-}-{-# LANGUAGE RankNTypes                 #-}-{-# LANGUAGE ScopedTypeVariables        #-}+{-# LANGUAGE StandaloneDeriving         #-} {-# LANGUAGE TupleSections              #-} {-# LANGUAGE TypeFamilies               #-}-{-# LANGUAGE UndecidableInstances       #-}+{-# LANGUAGE ViewPatterns               #-}  ------------------------------------------------------------------------------------- -- |@@ -31,12 +26,12 @@ module Music.Time.Chord (        -- * Chord type-      Chord,+      -- Chord,        -- * Construction-      chord,-      unchord,-      unsafeChord,+      -- chord,+      -- unchord,+      -- unsafeChord,        -- invertChord,       -- inversions,@@ -65,7 +60,7 @@ import           Data.VectorSpace import           Data.String -import           Music.Time.Delayed+import           Music.Time.Placed import           Music.Time.Reverse import           Music.Time.Split @@ -90,7 +85,7 @@ -- A 'Chord' is a parallel composition of values. -- -- @--- type Chord a = [Delayed a]+-- type Chord a = [Placed a] -- @ -- newtype Chord a = Chord { getChord :: ChordList (ChordEv a) }@@ -100,9 +95,9 @@ type ChordList = []  -- Can use any type as long as chordEv provides an Iso-type ChordEv a = Delayed a+type ChordEv a = Placed a -chordEv :: Iso (Delayed a) (Delayed b) (ChordEv a) (ChordEv b)+chordEv :: Iso (Placed a) (Placed b) (ChordEv a) (ChordEv b) chordEv = id  instance Applicative Chord where@@ -119,30 +114,30 @@  instance Rewrapped (Chord a) (Chord b) -instance Transformable (Chord a) where-  transform s = over _Wrapped' (transform s)--instance HasDuration (Chord a) where-  _duration = Foldable.sum . fmap _duration . view _Wrapped'+-- instance Transformable (Chord a) where+--   transform s = over _Wrapped' (transform s) -instance Splittable a => Splittable (Chord a) where+-- instance HasDuration (Chord a) where   -- TODO -instance Reversible a => Reversible (Chord a) where-  rev = over _Wrapped' (fmap rev) -- TODO OK?+-- instance Splittable a => Splittable (Chord a) where+--   -- TODO +-- instance Reversible a => Reversible (Chord a) where+--   rev = over _Wrapped' (fmap rev) -- TODO OK?+ -- TODO -- instance HasMeta (Chord a) where   -- meta = error "Not implemented: meta" -chord :: Getter [Delayed a] (Chord a)+chord :: Getter [Placed a] (Chord a) chord = from unsafeChord -unchord :: Lens (Chord a) (Chord b) [Delayed a] [Delayed b]+unchord :: Lens (Chord a) (Chord b) [Placed a] [Placed b] unchord = _Wrapped  -- TODO names are not consistent with other types-unsafeChord :: Iso (Chord a) (Chord b) [Delayed a] [Delayed b]+unsafeChord :: Iso (Chord a) (Chord b) [Placed a] [Placed b] unsafeChord = _Wrapped  instance IsString a => IsString (Chord a) where
− src/Music/Time/Delayed.hs
@@ -1,156 +0,0 @@--{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE ConstraintKinds            #-}-{-# LANGUAGE DeriveDataTypeable         #-}-{-# LANGUAGE DeriveFoldable             #-}-{-# LANGUAGE DeriveFunctor              #-}-{-# LANGUAGE DeriveTraversable          #-}-{-# LANGUAGE FlexibleContexts           #-}-{-# LANGUAGE FlexibleInstances          #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MultiParamTypeClasses      #-}-{-# LANGUAGE NoMonomorphismRestriction  #-}-{-# LANGUAGE RankNTypes                 #-}-{-# LANGUAGE ScopedTypeVariables        #-}-{-# LANGUAGE StandaloneDeriving         #-}-{-# LANGUAGE TupleSections              #-}-{-# LANGUAGE TypeFamilies               #-}-{-# LANGUAGE UndecidableInstances       #-}------------------------------------------------------------------------------------------ |--- Copyright   : (c) Hans Hoglund 2012-2014------ License     : BSD-style------ Maintainer  : hans@hanshoglund.se--- Stability   : experimental--- Portability : non-portable (TF,GNTD)-------------------------------------------------------------------------------------------module Music.Time.Delayed (-        -- * Delayed type-        Delayed,--        -- * Construction-        delayed,-        delayedValue,-  ) where--import           Data.AffineSpace-import           Data.AffineSpace.Point-import           Data.Bifunctor-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.VectorSpace-import           Data.String-import           Data.Functor.Adjunction  (unzipR)--import           Control.Applicative-import           Control.Comonad-import           Control.Comonad.Env-import           Control.Lens           hiding (Indexable, Level, above, below,-                                         index, inside, parts, reversed,-                                         transform, (<|), (|>))-import           Data.Foldable          (Foldable)-import qualified Data.Foldable          as Foldable-import           Data.PairMonad-import           Data.Typeable--import           Music.Dynamics.Literal-import           Music.Pitch.Literal-import           Music.Time.Reverse-import           Music.Time.Split----- |--- 'Delayed' represents a value with an offset in time.------ A delayed value has a known 'position', but no 'duration'.------ Placing a value inside 'Delayed' does not make it invariant under 'stretch', as the--- offset of a delayed value may be stretched with respect to the origin. However, in--- contrast to a note the /duration/ is not stretched.----newtype Delayed a = Delayed   { _delayedValue :: (Time, a) }-  deriving (Eq, {-Ord, -}{-Show, -}-            Applicative, Monad, {-Comonad, -}-            Functor,  Foldable, Traversable, Typeable)---- $semantics Delayed------ @--- type Delayed a = (Time, a)--- @-----instance (Show a, Transformable a) => Show (Delayed a) where-  show x = show (x^.from delayed) ++ "^.delayed"--instance Wrapped (Delayed a) where-  type Unwrapped (Delayed a) = (Time, a)-  _Wrapped' = iso _delayedValue Delayed--instance Rewrapped (Delayed a) (Delayed b)--instance Transformable (Delayed a) where-  transform t = over _Wrapped $ first (transform t)--instance HasDuration (Delayed a) where-  _duration x = _offset x .-. _onset x--instance HasPosition (Delayed a) where-  x `_position` p = ask (view _Wrapped x) `_position` p--instance Reversible (Delayed a) where-  rev = revDefault--instance Splittable a => Splittable (Delayed a) where-  -- TODO is this right?-  split t = unzipR . fmap (split t)---- Lifted instances--instance IsString a => IsString (Delayed a) where-  fromString = pure . fromString--instance IsPitch a => IsPitch (Delayed a) where-  fromPitch = pure . fromPitch--instance IsInterval a => IsInterval (Delayed a) where-  fromInterval = pure . fromInterval--instance IsDynamics a => IsDynamics (Delayed a) where-  fromDynamics = pure . fromDynamics---- |--- View a delayed value as a pair of a the original value and a delay time.----delayed :: Iso (Time, a) (Time, b) (Delayed a) (Delayed b)-delayed = _Unwrapped----- |--- View a delayed value as a pair of the original value and the transformation (and vice versa).----delayedValue :: (Transformable a, Transformable b)-  => Lens-      (Delayed a) (Delayed b)-      a b-delayedValue = lens runDelayed (flip $ _delayed . const)-  where-    _delayed f (Delayed (t,x)) = Delayed (t, f `whilst` delaying (t .-. 0) $ x)-{-# INLINE delayedValue #-}---runDelayed :: Transformable a => Delayed a -> a-runDelayed = uncurry delayTime . view _Wrapped-  where-    delayTime t = delay (t .-. 0)--
src/Music/Time/Duration.hs view
@@ -1,14 +1,15 @@ -{-# LANGUAGE ConstraintKinds           #-}-{-# LANGUAGE FlexibleContexts          #-}-{-# LANGUAGE FlexibleInstances         #-}-{-# LANGUAGE MultiParamTypeClasses     #-}-{-# LANGUAGE NoMonomorphismRestriction #-}-{-# LANGUAGE RankNTypes                #-}-{-# LANGUAGE ScopedTypeVariables       #-}-{-# LANGUAGE TupleSections             #-}-{-# LANGUAGE TypeFamilies              #-}-{-# LANGUAGE UndecidableInstances      #-}+{-# LANGUAGE ConstraintKinds            #-}+{-# LANGUAGE DeriveDataTypeable         #-}+{-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE DeriveFoldable             #-}+{-# LANGUAGE DeriveTraversable          #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses      #-}+{-# LANGUAGE StandaloneDeriving         #-}+{-# LANGUAGE TupleSections              #-}+{-# LANGUAGE TypeFamilies               #-}+{-# LANGUAGE ViewPatterns               #-}  ------------------------------------------------------------------------------------- -- |@@ -55,9 +56,6 @@ class HasDuration a where   _duration :: a -> Duration -instance HasDuration Time where-  _duration = 0- instance HasDuration Duration where   _duration = id @@ -98,34 +96,16 @@   _duration (Right x) = _duration x  -- |--- Access the duration.----duration :: (Transformable a, HasDuration a) => Lens' a Duration-duration = lens _duration (flip stretchTo)-{-# INLINE duration #-}---- | -- Stretch a value to have the given duration. -- stretchTo :: (Transformable a, HasDuration a) => Duration -> a -> a stretchTo d x = (d ^/ _duration x) `stretch` x {-# INLINE stretchTo #-} -{----- TODO more general pattern here-withDurationR :: (Functor f, HasDuration a) => f a -> f (Duration, a)-withDurationR = fmap $ \x -> (_duration x, x)--withDurationL :: (Contravariant f, HasDuration a) => f (Duration, a) -> f a-withDurationL = contramap $ \x -> (_duration x, x)--mapWithDuration :: HasDuration a => (Duration -> a -> b) -> a -> b-mapWithDuration = over dual withDurationL . uncurry-  where-    dual :: Iso (a -> b) (c -> d) (Op b a) (Op d c)-    dual = iso Op getOp---}-+-- |+-- Access the duration.+--+duration :: (Transformable a, HasDuration a) => Lens' a Duration+duration = lens _duration (flip stretchTo)+{-# INLINE duration #-} 
+ src/Music/Time/Event.hs view
@@ -0,0 +1,271 @@++{-# LANGUAGE DeriveDataTypeable         #-}+{-# LANGUAGE DeriveFoldable             #-}+{-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE DeriveTraversable          #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses      #-}+{-# LANGUAGE StandaloneDeriving         #-}+{-# LANGUAGE TypeFamilies               #-}+{-# LANGUAGE ViewPatterns               #-}+{-# LANGUAGE TypeOperators              #-}+{-# LANGUAGE RankNTypes                 #-}+{-# LANGUAGE TupleSections              #-}+{-# LANGUAGE FlexibleContexts              #-}++-------------------------------------------------------------------------------------+-- |+-- Copyright   : (c) Hans Hoglund 2012-2014+--+-- License     : BSD-style+--+-- Maintainer  : hans@hanshoglund.se+-- Stability   : experimental+-- Portability : non-portable (TF,GNTD)+--+-------------------------------------------------------------------------------------++module Music.Time.Event (+        -- * Event type+        Event,++        -- * Construction+        event,+        eventee,+        spanEvent,+        triple+  ) where++import           Control.Applicative+import           Control.Monad (join, mapM)+import           Data.Semigroup+import           Data.Functor.Couple+import           Data.Functor.Classes+import           Data.Functor.Compose+import           Control.Monad.Compose+import           Control.Comonad+import           Control.Lens             hiding (Indexable, Level, above,+                                           below, index, inside, parts,+                                           reversed, transform, (<|), (|>))+import           Data.PairMonad+import           Data.String+import           Data.VectorSpace+import           Data.Foldable            (Foldable)+import qualified Data.Foldable            as Foldable+import           Data.Typeable++import           Music.Dynamics.Literal+import           Music.Pitch.Literal+import           Music.Time.Internal.Util (through, tripped)+import           Music.Time.Reverse+import           Music.Time.Split+import           Music.Time.Meta+++-- |+-- A 'Event' is a value with an 'onset' and and 'offset' in time. It is an instance+-- of 'Transformable'.+--+-- You can use 'value' to apply a function in the context of the transformation,+-- i.e.+--+-- @+-- over value (* line) (delay 2 $ return line)+-- @+--+-- @+-- ('view' 'value') . 'transform' s = 'transform' s . ('view' 'value')+-- @+--++-- TODO+instance Traversable AddMeta where+  traverse = annotated+instance Eq1 AddMeta where+  eq1 = (==)+instance Eq a => Eq1 (Couple a) where+  eq1 = (==)+instance Ord1 AddMeta where+  compare1 = compare+instance Ord a => Ord1 (Couple a) where+  compare1 = compare+instance Num (f (g a)) => Num (Compose f g a) where+  Compose a + Compose b = Compose (a + b)+  Compose a - Compose b = Compose (a - b)+  Compose a * Compose b = Compose (a * b)+  signum (Compose a) = Compose (signum a)+  abs (Compose a) = Compose (abs a)+  fromInteger = Compose . fromInteger+instance Fractional (f (g a)) => Fractional (Compose f g a) where+  Compose a / Compose b = Compose (a / b)+  fromRational = Compose . fromRational+instance Floating (f (g a)) => Floating (Compose f g a) where+  +instance (Real (f (g a)), Ord1 f, Ord1 g, Ord a, Functor f) => Real (Compose f g a) where+  -- TODO+instance (RealFrac (f (g a)), Ord1 f, Ord1 g, Ord a, Functor f) => RealFrac (Compose f g a) where+  -- TODO+instance (Functor f, Monad f, Monad g, Traversable g) => Monad (Compose f g) where+  return = Compose . return . return+  xs >>= f = Compose $ mbind (getCompose . f) (getCompose xs)+instance (Comonad f, Comonad g) => Comonad (Compose f g) where+  extract (Compose f) = (extract . extract) f+  -- TODO duplicate+  +newtype Event a = Event { getEvent :: Compose AddMeta (Couple Span) a }+  deriving (+    Eq,+    Ord,+    Typeable,+    Foldable,+    Applicative,+    Monad,+    Comonad,+    Traversable,+    +    Functor,+    +    Num,+    Fractional,+    Floating,+    Real,+    RealFrac+    )  ++instance Wrapped (Event a) where+  type Unwrapped (Event a) = AddMeta (Span, a)+  _Wrapped' = iso (fmap getCouple . getCompose . getEvent) (Event . Compose . fmap Couple)++instance Rewrapped (Event a) (Event b)++instance Transformable (Event a) where+  transform t = over eventSpan (transform t)++instance HasDuration (Event a) where+  _duration = _duration . _era++instance HasPosition (Event a) where+  _era = view eventSpan++instance HasMeta (Event a) where+  meta = _Wrapped . meta++instance IsString a => IsString (Event a) where+  fromString = pure . fromString++instance IsPitch a => IsPitch (Event a) where+  fromPitch = pure . fromPitch++instance IsInterval a => IsInterval (Event a) where+  fromInterval = pure . fromInterval++instance IsDynamics a => IsDynamics (Event a) where+  fromDynamics = pure . fromDynamics++instance (Show a, Transformable a) => Show (Event a) where+  show x = show (x^.from event) ++ "^.event"++-- | View a event as a pair of the original value and the transformation (and vice versa).+event :: Iso (Span, a) (Span, b) (Event a) (Event b)+event = from (_Wrapped . unsafeAnnotated)+-- TODO not safe anymore...++-- safeUnevent = _Wrapped . annotated == from event+eventSpan :: Lens' (Event a) Span+eventSpan = from event . _1++eventValue :: Lens (Event a) (Event b) a b+eventValue = from event . _2++-- | View the value in the event.+eventee :: (Transformable a, Transformable b) => Lens (Event a) (Event b) a b+eventee = from event `dependingOn` (transformed)++-- | Event as a span with a trivial value.+spanEvent :: Iso' Span (Event ())+spanEvent = iso (\s -> (s,())^.event) (^.era)++-- | View a event as a @(time, duration, value)@ triple.+triple :: Iso (Event a) (Event b) (Time, Duration, a) (Time, Duration, b)+triple = from event . bimapping delta id . tripped+++-- TODO consolidate+dependingOn :: Lens s t (x,a) (x,b) -> (x -> Lens a b c d) -> Lens s t c d+dependingOn l depending f = l (\ (x,a) -> (x,) <$> depending x f a)++++++++++-- newtype AddMeta1 f a = AddMeta1 { getAddMeta1 :: Twain Meta (f a) }+--   deriving (+--     )+-- +-- instance Wrapped (AddMeta1 f a) where+--   type Unwrapped (AddMeta1 f a) = Twain Meta (f a)+--   _Wrapped' = iso getAddMeta1 AddMeta1+-- +-- instance Rewrapped (AddMeta1 f a) (AddMeta1 f b)+-- +-- instance HasMeta (AddMeta1 f a) where+--   -- twain, pair, element+--   meta = _Wrapped . _Wrapped . _1+-- +-- +-- -- instance FunctorWithIndex i AddMeta1 where+--   -- imap f = over annotated $ imap f+-- -- +-- -- instance FoldableWithIndex Span Score where+-- --   ifoldMap f (Score (m,x)) = ifoldMap f x+-- -- +-- -- instance TraversableWithIndex Span Score where+-- --   itraverse f (Score (m,x)) = fmap (\x -> Score (m,x)) $ itraverse f x+-- +-- instance Transformable (f a) => Transformable (AddMeta1 f a) where+--   transform t = over meta (transform t) . over annotated1 (transform t)+-- +-- instance Reversible (f a) => Reversible (AddMeta1 f a) where+--   rev = over meta rev . over annotated1 rev+-- +-- -- instance Splittable a => Splittable (AddMeta1 a) where+-- --   split t = unzipR . fmap (split t)+-- +-- instance HasPosition (f a) => HasPosition (AddMeta1 f a) where+--   _era = _era . extract+--   _position = _position . extract+-- +-- instance HasDuration (f a) => HasDuration (AddMeta1 f a) where+--   _duration = _duration . extract+-- +-- -- |+-- -- Access the annotated value.+-- --+-- -- @+-- -- over annotated = fmap+-- -- @+-- --+-- annotated1 :: Lens (AddMeta1 f a) (AddMeta1 f b) (f a) (f b)+-- annotated1 = unsafeAnnotated1+-- +-- -- |+-- -- Access the annotated value.+-- --+-- -- @+-- -- view fromAnnotated = pure+-- -- @+-- --+-- unannotated1 :: Getter (f a) (AddMeta1 f a)+-- unannotated1 = from unsafeAnnotated1+-- +-- unsafeAnnotated1 :: Iso (AddMeta1 f a) (AddMeta1 f b) (f a) (f b)+-- unsafeAnnotated1 = _Wrapped . extracted+-- +-- unzipR f = (map fst f, map snd f)+-- +-- extracted :: (Applicative m, Comonad m) => Iso (m a) (m b) a b+-- extracted = iso extract pure
src/Music/Time/Future.hs view
@@ -1,6 +1,19 @@ +-------------------------------------------------------------------------------------+-- |+-- Copyright   : (c) Hans Hoglund 2012-2014+--+-- License     : BSD-style+--+-- Maintainer  : hans@hanshoglund.se+-- Stability   : experimental+-- Portability : non-portable (TF,GNTD)+--+-------------------------------------------------------------------------------------+ module Music.Time.Future (     module Music.Time.Past ) where +-- Future and Past are defined together in this module for now.  import Music.Time.Past
src/Music/Time/Graces.hs view
@@ -1,17 +1,15 @@  {-# LANGUAGE ConstraintKinds            #-} {-# LANGUAGE DeriveDataTypeable         #-}-{-# LANGUAGE DeriveFoldable             #-} {-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE DeriveFoldable             #-} {-# LANGUAGE DeriveTraversable          #-}-{-# LANGUAGE FlexibleContexts           #-}-{-# LANGUAGE FlexibleInstances          #-}-{-# LANGUAGE GADTs                      #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE MultiParamTypeClasses      #-}-{-# LANGUAGE ScopedTypeVariables        #-}+{-# LANGUAGE StandaloneDeriving         #-}+{-# LANGUAGE TupleSections              #-} {-# LANGUAGE TypeFamilies               #-}+{-# LANGUAGE ViewPatterns               #-}  ------------------------------------------------------------------------------------- -- |
src/Music/Time/Internal/Convert.hs view
@@ -25,10 +25,8 @@ -------------------------------------------------------------------------------------  module Music.Time.Internal.Convert (-        voiceToScore,-        voiceToScore',         scoreToVoice,-        reactiveToVoice',+        reactiveToVoice'   ) where  import           Control.Applicative@@ -51,34 +49,8 @@ import qualified Data.List              as List  -{---- | Convert a note to an _onset and a voice.-noteToVoice :: Note a -> (Time, Voice a)-noteToVoice (view (from note) -> (s,x)) = (_onset s, stretchTo (_duration s) $ return x)--}--{---- | Convert a note to a score.-noteToScore :: Note a -> Score a-noteToScore (view (from note) -> (s,x)) = s `transform` return x--}---- scoreToNotes :: Score a -> [Note a]--- scoreToNotes = Foldable.toList . reifyScore---- notesToScore :: [Note a] -> Score a--- notesToScore = pcat . fmap noteToScore--{--reactiveToVoice :: Duration -> Reactive a -> Voice a-reactiveToVoice d r = (^. voice) $ fmap (^. stretched) $ durs `zip` (fmap (r `atTime`) times)-    where-        times = 0 : filter (\t -> 0 < t && t < 0 .+^ d) (occs r)-        durs  = toRelativeTimeN' (0 .+^ d) times--}- reactiveToVoice' :: Span -> Reactive a -> Voice a-reactiveToVoice' (view range -> (u,v)) r = (^. voice) $ fmap (^. stretched) $ durs `zip` (fmap (r `atTime`) times)+reactiveToVoice' (view range -> (u,v)) r = (^. voice) $ fmap (^. note) $ durs `zip` (fmap (r `atTime`) times)     where         times = 0 : filter (\t -> u < t && t < v) (occs r)         durs  = toRelativeTimeN' v times@@ -88,7 +60,7 @@ -- Convert a score to a voice. Fails if the score contain overlapping events. -- scoreToVoice :: Transformable a => Score a -> Voice (Maybe a)-scoreToVoice = (^. voice) . fmap (^. stretched) . fmap throwTime . addRests . (^. events)+scoreToVoice = (^. voice) . fmap (^. note) . fmap throwTime . addRests . (^. triples)     where        throwTime (t,d,x) = (d,x)        addRests = concat . snd . mapAccumL g 0@@ -99,77 +71,8 @@                    | otherwise = error "scoreToVoice: Strange prevTime" {-# DEPRECATED scoreToVoice "" #-} --- |--- Convert a voice to a score.----voiceToScore :: Voice a -> Score a-voiceToScore = scat . fmap g . (^. stretcheds) where g = (^. stretchedValue) . fmap return-{-# DEPRECATED voiceToScore "" #-}- {---- | Join voices in a given part into a score.-voicesToScore :: HasPart a => [(Part a, Voice a)] -> Score a-voicesToScore = pcat . fmap (voiceToScore . uncurry (\n -> fmap (setPart n)))--}---- |--- Convert a voice which may contain rests to a score.----voiceToScore' :: Voice (Maybe a) -> Score a-voiceToScore' = mcatMaybes . voiceToScore-{-# DEPRECATED voiceToScore' "" #-}--{---- |--- Convert a track to a score where each event is given a fixed duration.----trackToScore :: Transformable a => Duration -> Track a -> Score a-trackToScore x = trackToScore' (const x)---- |--- Convert a track to a score, using durations determined by the values.----trackToScore' :: Transformable a => (a -> Duration) -> Track a -> Score a-trackToScore' f = (^. from events) . fmap (\(t,x) -> (t,f x,x)) . map (^. from delayed) . (^. delayeds)+voiceToScore :: Voice a -> Score a+voiceToScore = renderAlignedVoice . aligned (0 :: Time) (0 :: LocalDuration) -}----- TODO rename during-noteToReactive :: Monoid a => Note a -> Reactive a-noteToReactive n = (pure <$> n) `activate` pure mempty---- JUNK---- | Split a reactive into mkNotes, as well as the values before and after the first/last update-splitReactive :: Reactive a -> Either a ((a, Time), [Note a], (Time, a))-splitReactive r = case updates r of-    []          -> Left  (initial r)-    (t,x):[]    -> Right ((initial r, t), [], (t, x))-    (t,x):xs    -> Right ((initial r, t), fmap mkNote $ mrights (res $ (t,x):xs), head $ mlefts (res $ (t,x):xs))--    where--        mkNote (t,u,x) = (t <-> u, x)^.note--        -- Always returns a 0 or more Right followed by one left-        res :: [(Time, a)] -> [Either (Time, a) (Time, Time, a)]-        res rs = let (ts,xs) = unzip rs in-            flip fmap (withNext ts `zip` xs) $-                \ ((t, mu), x) -> case mu of-                    Nothing -> Left (t, x)-                    Just u  -> Right (t, u, x)--        -- lenght xs == length (withNext xs)-        withNext :: [a] -> [(a, Maybe a)]-        withNext = go-            where-                go []       = []-                go [x]      = [(x, Nothing)]-                go (x:y:rs) = (x, Just y) : withNext (y : rs)--activate :: Note (Reactive a) -> Reactive a -> Reactive a-activate (view (from note) -> (view range -> (start,stop), x)) y = y `turnOn` (x `turnOff` y)-  where-    turnOn  = switchR start-    turnOff = switchR stop 
src/Music/Time/Internal/Quantize.hs view
@@ -76,8 +76,8 @@ getBeatDuration _          = error "getBeatValue: Not a beat"  -- TODO return voice-realize :: Rhythm a -> [Stretched a]-realize (Beat d a)      = [(d, a)^.stretched]+realize :: Rhythm a -> [Note a]+realize (Beat d a)      = [(d, a)^.note] realize (Group rs)      = rs >>= realize realize (Dotted n r)    = dotMod n `stretch` realize r realize (Tuplet n r)    = n `stretch` realize r@@ -184,7 +184,7 @@ tupletDot orig                                                       = orig  splitTupletIfLongEnough :: Rhythm a -> Rhythm a-splitTupletIfLongEnough r = if _duration r > (1/4) then splitTuplet r else r+splitTupletIfLongEnough r = if _duration r > (1/2) then splitTuplet r else r -- TODO should compare against beat duration, not just (1/4)  -- | Splits a tuplet iff it contans a group which can be split into two halves whose
src/Music/Time/Internal/Transform.hs view
@@ -34,9 +34,7 @@          -- * The Transformable class         Transformable(..),-        itransform,         transformed,-        itransformed,          -- * Apply under a transformation         whilst,@@ -46,7 +44,6 @@         whilstLD,         whilstStretch,         whilstDelay,-        spanned,         onSpan,         conjugateS, @@ -86,36 +83,21 @@ import qualified Data.Set               as Set import           Data.VectorSpace       hiding (Sum (..)) --- |--- Class of values that can be transformed (i.e. scaled and moved) in time.------ Law------ @--- transform mempty = id--- transform (s \<> t) = transform s . transform t--- transform (s \<> negateV s) = id--- @------ Law------ @--- onset (delay n a)       = n ^+. onset a--- offset (delay n a)      = n ^+. offset a--- duration (stretch n a)  = n * duration a--- duration (compress n a) = duration a / n--- @+-- Transformable laws:+-- > transform mempty   = id+-- > transform (s <> t) = transform s . transform t ----- @--- delay n b ! t    = b ! (t .-^ n)--- undelay n b ! t  = b ! (t .+^ n)--- @+-- Duration law:+-- > _duration a = _duration (_era a) ----- Lemma+-- Position law:+-- > _position p (transform s a) = transform s (_position p a) ----- @--- duration a = duration (delay n a)--- @+-- Lemma:+-- > _duration (transform s a) = transform s (_duration a)++-- |+-- Class of values that can be transformed (i.e. scaled and moved) in time. -- class Transformable a where   transform :: Span -> a -> a@@ -183,48 +165,26 @@ instance (Ord k, Transformable a) => Transformable (Map k a) where   transform t = Map.map (transform t) --- | -- Functions transform by conjugation, i.e. we reverse-transform the argument -- and transform the result. -- instance (Transformable a, Transformable b) => Transformable (a -> b) where   transform t = (`whilst` negateV t)----- |--- Apply the inverse of the given transformation.------ @--- 'itransform' s = 'transform' ('negateV' s)--- @----itransform :: Transformable a => Span -> a -> a-itransform s = transform (negateV s)+    where+    f `whilst` t = over (transformed t) f  -- | -- View the given value in the context of the given transformation. -- transformed :: (Transformable a, Transformable b) => Span -> Iso a b a b-transformed s = iso (transform s) (itransform s)+transformed s = iso (transform s) (transform $ negateV s)   -- |--- Transforms a lens of to a 'Transformable' type to act inside a transformation.----itransformed :: (Transformable a, Transformable b) => Span -> Iso a b a b-itransformed s = transformed (negateV s)--spanned = itransformed-{-# DEPRECATED spanned "Use itransformed" #-}---- | -- Apply a function under transformation. ----- Designed to be used infix, as in------ @--- 'stretch' 2 `whilst` 'delaying' 2--- @+-- >>> stretch 2 `whilst` delaying 2 $ (1 <-> 2)+-- 4 <-> 6 -- whilst :: (Transformable a, Transformable b) => (a -> b) -> Span -> a -> b -- f `whilst` t = transform (negateV t) . f . transform t@@ -436,7 +396,7 @@ -- onSpan :: (Transformable s, Transformable t, Functor f)    => LensLike f s t a b -> Span -> LensLike f s t a b-f `onSpan` s = spanned s . f+f `onSpan` s = transformed (negateV s) . f -- TODO name  -- deriving instance Functor Sum
src/Music/Time/Internal/Util.hs view
@@ -29,6 +29,7 @@   partial,   partial2,   partial3,+  _zipList,   ) where  {-@@ -360,16 +361,20 @@ through lens1 lens2 = lens getter (flip setter)   where     getter = fmap (view lens1)-    setter = liftA2 (over lens2 . const)+    setter = liftA2 (set lens2) {-# INLINE through #-} +_zipList :: Iso [a] [b] (ZipList a) (ZipList b)+_zipList = iso ZipList getZipList++ single :: Prism' [a] a single = prism' return $ \xs -> case xs of   [x] -> Just x   _   -> Nothing {-# INLINE single #-} -tripped :: Iso ((a, b), c) ((a', b'), c') (a, b, c) (a', b', c')+tripped :: Iso ((a, b), c) ((d, e), f) (a, b, c) (d, e, f) tripped = iso tripl untripl {-# INLINE tripped #-} 
src/Music/Time/Juxtapose.hs view
@@ -1,7 +1,5 @@  {-# LANGUAGE ConstraintKinds           #-}-{-# LANGUAGE FlexibleContexts          #-}-{-# LANGUAGE FlexibleInstances         #-} {-# LANGUAGE MultiParamTypeClasses     #-} {-# LANGUAGE NoMonomorphismRestriction #-} {-# LANGUAGE RankNTypes                #-}
src/Music/Time/Meta.hs view
@@ -12,6 +12,7 @@ {-# LANGUAGE MultiParamTypeClasses      #-} {-# LANGUAGE ScopedTypeVariables        #-} {-# LANGUAGE TypeFamilies               #-}+{-# LANGUAGE TypeOperators              #-}  ------------------------------------------------------------------------------------- -- |@@ -236,7 +237,7 @@ -- -- You can access the meta-data using 'meta', and the annotated value using 'annotated'. ---newtype AddMeta a = AddMeta { getAddMeta :: Twain Meta a }+newtype AddMeta a = AddMeta { getAddMeta :: Meta `Twain` a }   deriving (     Show, Functor, Foldable, Typeable, Applicative, Monad, Comonad,     Semigroup, Monoid, Num, Fractional, Floating, Enum, Bounded,@@ -274,8 +275,7 @@   split t = unzipR . fmap (split t)  instance HasPosition a => HasPosition (AddMeta a) where-  _onset    = _onset . extract-  _offset   = _offset . extract+  _era = _era . extract   _position = _position . extract  instance HasDuration a => HasDuration (AddMeta a) where
src/Music/Time/Nominal.hs view
@@ -1,17 +1,16 @@  {-# LANGUAGE ConstraintKinds            #-} {-# LANGUAGE DeriveDataTypeable         #-}-{-# LANGUAGE DeriveFoldable             #-} {-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE DeriveFoldable             #-} {-# LANGUAGE DeriveTraversable          #-} {-# LANGUAGE FlexibleContexts           #-}-{-# LANGUAGE FlexibleInstances          #-}-{-# LANGUAGE GADTs                      #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE MultiParamTypeClasses      #-}-{-# LANGUAGE ScopedTypeVariables        #-}+{-# LANGUAGE StandaloneDeriving         #-}+{-# LANGUAGE TupleSections              #-} {-# LANGUAGE TypeFamilies               #-}+{-# LANGUAGE ViewPatterns               #-}  ------------------------------------------------------------------------------------- -- |@@ -41,7 +40,16 @@ import Music.Time.Reverse  newtype Nominal f a = Nominal { getNominal :: f a }-  deriving (Eq, Ord, Read, Show, Functor, Foldable, Traversable, Monad)+  deriving (+  	Eq, +  	Ord,+  	Read, +  	Show, +  	Functor, +  	Foldable, +  	Traversable, +  	Monad+  )  instance Applicative f => Applicative (Nominal f) where   pure = Nominal . pure
src/Music/Time/Note.hs view
@@ -1,21 +1,14 @@ -{-# LANGUAGE ConstraintKinds            #-} {-# LANGUAGE DeriveDataTypeable         #-} {-# LANGUAGE DeriveFoldable             #-} {-# LANGUAGE DeriveFunctor              #-} {-# LANGUAGE DeriveTraversable          #-}-{-# LANGUAGE FlexibleContexts           #-}-{-# LANGUAGE FlexibleInstances          #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses      #-}-{-# LANGUAGE NoMonomorphismRestriction  #-} {-# LANGUAGE RankNTypes                 #-}-{-# LANGUAGE ScopedTypeVariables        #-}-{-# LANGUAGE StandaloneDeriving         #-}-{-# LANGUAGE TupleSections              #-} {-# LANGUAGE TypeFamilies               #-}-{-# LANGUAGE UndecidableInstances       #-}-{-# LANGUAGE ViewPatterns               #-}+{-# LANGUAGE TypeOperators              #-}+{-# LANGUAGE TupleSections              #-}  ------------------------------------------------------------------------------------- -- |@@ -32,108 +25,73 @@ module Music.Time.Note (         -- * Note type         Note,-         -- * Construction         note,-        event,-        noteValue,      +        notee,+        durationNote,+        -- noteComplement,   ) 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           Control.Applicative-import           Control.Comonad-import           Control.Comonad.Env import           Control.Lens           hiding (Indexable, Level, above, below,                                          index, inside, parts, reversed,                                          transform, (<|), (|>))+import           Data.Bifunctor import           Data.Foldable          (Foldable) import qualified Data.Foldable          as Foldable-import           Data.PairMonad+import           Data.Functor.Couple+import           Data.String import           Data.Typeable+import           Data.VectorSpace -import           Music.Pitch.Literal import           Music.Dynamics.Literal-import           Music.Time.Internal.Util (through, tripped)-+import           Music.Pitch.Literal import           Music.Time.Reverse import           Music.Time.Split   -- |--- A 'Note' is a value with an 'onset' and and 'offset' in time. It is an instance--- of 'Transformable'.------ You can use 'value' to apply a function in the context of the transformation,--- i.e.------ @--- over value (* line) (delay 2 $ return line)--- @+-- A value 'Note' value, representing a suspended stretch of some 'Transformable'+-- value. We can access the value in bothits original and note form using 'note'+-- and 'notee', respectively. ----- @--- ('view' 'value') . 'transform' s = 'transform' s . ('view' 'value')--- @+-- Placing a value inside 'Note' makes it invariant under 'delay', however the inner+-- value can still be delayed using @'fmap' 'delay'@. ---newtype Note a = Note { _noteValue :: (Span, a) }-  deriving (Typeable)+newtype Note a = Note { getNote :: Duration `Couple` a }+  deriving (+    Eq,+    Ord,+    Typeable,+    Foldable,+    Traversable, --- $semantics------ type Note a = (Span, a)---+    Functor,+    Applicative,+    Monad, -deriving instance Eq a => Eq (Note a)-deriving instance Functor Note-deriving instance Foldable Note-deriving instance Traversable Note-deriving instance Comonad Note+    Num,+    Fractional,+    Floating,+    Real,+    RealFrac+    )+            -- Comonad,  instance (Show a, Transformable a) => Show (Note a) where   show x = show (x^.from note) ++ "^.note" --- |--- Note is a 'Monad' and 'Applicative' in the style of pair, with 'return' placing a value--- at the default span 'mempty' and 'join' composing time transformations.-deriving instance Monad Note-deriving instance Applicative Note---- instance ComonadEnv Span Note where-  -- ask = noteValueSpan- instance Wrapped (Note a) where-  type Unwrapped (Note a) = (Span, a)-  _Wrapped' = iso _noteValue Note+  type Unwrapped (Note a) = (Duration, a)+  _Wrapped' = iso (getCouple . getNote) (Note . Couple)  instance Rewrapped (Note a) (Note b)  instance Transformable (Note a) where-  transform t = over (_Wrapped . _1) $ transform t+  transform t = over (from note . _1) (transform t)  instance HasDuration (Note a) where-  _duration = _duration . ask . view _Wrapped--instance HasPosition (Note a) where-  x `_position` p = ask (view _Wrapped x) `_position` p--instance Splittable a => Splittable (Note a) where-  -- beginning d = over _Wrapped $ \(s, v) -> (beginning d s, beginning (transform (negateV s) d) v)-  beginning d = over _Wrapped $ \(s, v) -> (beginning d s, beginning (d / _duration s) v)-  ending    d = over _Wrapped $ \(s, v) -> (ending    d s, ending    (d / _duration s) v)--instance Reversible (Note a) where-  rev = revDefault---- Lifted instances+  _duration = _duration . view (from note)  instance IsString a => IsString (Note a) where   fromString = pure . fromString@@ -147,28 +105,50 @@ instance IsDynamics a => IsDynamics (Note a) where   fromDynamics = pure . fromDynamics --- |--- View a note as a pair of the original value and the transformation (and vice versa).----note :: ({-Transformable a, Transformable b-}) => Iso (Span, a) (Span, b) (Note a) (Note b)+-- | View a note value as a pair of the original value and a stretch factor.+note :: Iso (Duration, a) (Duration, b) (Note a) (Note b) note = _Unwrapped --- |--- View the value in the note.+-- | Access the note value.+-- Taking a value out carries out the stretch (using the 'Transformable' instance),+-- while putting a value in carries out the reverse transformation. ---noteValue :: (Transformable a, Transformable b) => Lens (Note a) (Note b) a b-noteValue = lens runNote (flip $ mapNote . const)-  where-    runNote = uncurry transform . view _Wrapped-    -- setNote f (view (from note) -> (s,x)) = view note (s, itransform s x)-    mapNote f (view (from note) -> (s,x)) = view note (s, f `whilst` negateV s $ x)-{-# INLINE noteValue #-}+-- >>> view notee $ (2,3::Duration)^.note+-- 6+--+-- >>> set notee 6 $ (2,1::Duration)^.note+-- (2,3)^.note+--+notee :: (Transformable a, Transformable b) => Lens (Note a) (Note b) a b+notee = _Wrapped `dependingOn` (transformed . stretching) --- |--- View a note as an events, i.e. a time-duration-value triplet.+-- | A note value as a duration carrying an associated value.+-- Whitness by picking a trivial value. ---event :: Iso (Note a) (Note b) (Time, Duration, a) (Time, Duration, b)-event = from note . bimapping delta id . tripped+-- >>> 2^.durationNote+-- (2,())^.note+--+durationNote :: Iso' Duration (Note ())+durationNote = iso (\d -> (d,())^.note) (^.duration)++-- >>> (pure ())^.from durationNote+-- 1+-- >>> (pure () :: Note ())^.duration+-- 1++-- TODO could also be an iso...+noteComplement :: Note a -> Note a+noteComplement (Note (Couple (d,x))) = Note $ Couple (negateV d, x)++-- FIXME negateV is negate not recip+-- The negateV method should follow (^+^), which is (*) for durations (is this bad?)+++-- TODO consolidate+dependingOn :: Lens s t (x,a) (x,b) -> (x -> Lens a b c d) -> Lens s t c d+dependingOn l depending f = l (\ (x,a) -> (x,) <$> depending x f a)++   
src/Music/Time/Past.hs view
@@ -5,7 +5,16 @@ {-# LANGUAGE ViewPatterns               #-} {-# LANGUAGE CPP #-} -module Music.Time.Past where+module Music.Time.Past (+        Past(..),+        Future(..),+        past,+        future,+        indexPast,+        firstTrue,+        pastSeg,+        futureSeg,+  ) where  import Control.Lens -- DEBUG import           Control.Applicative@@ -28,7 +37,7 @@ -- -- It may be seen as a note whose era is a left-open, right-inclusive time interval. ---newtype Past a = Past { getPast :: (Min Time, a) }+newtype Past a = Past { getPast :: (Min (Maybe Time), a) }   deriving (Eq, Ord, Functor)  -- |@@ -36,36 +45,38 @@ -- -- It may be seen as a note whose era is a left-open, right-inclusive time interval. ---newtype Future a = Future { getFuture :: (Max Time, a) }+newtype Future a = Future { getFuture :: (Max (Maybe Time), a) }   deriving (Eq, Ord, Functor) -instance HasDuration (Past a) where-  _duration _ = 0--instance HasDuration (Future a) where-  _duration _ = 0--instance HasPosition (Past a) where-  _position (Past (extract -> t,_)) _ = t--instance HasPosition (Future a) where-  _position (Future (extract -> t,_)) _ = t+-- instance HasDuration (Past a) where+--   _duration _ = 0+-- +-- instance HasDuration (Future a) where+--   _duration _ = 0+-- +-- instance HasPosition (Past a) where+--   _position (Past ((extract . extract) -> t,_)) _ = t+-- +-- instance HasPosition (Future a) where+  -- _position (Future (extract -> t,_)) _ = t  -- | Query a past value. Semantic function. past :: Past a -> Time -> Maybe a past (Past (extract -> t, x)) t'-  | t' <= t    = Just x-  | otherwise  = Nothing+  | Just t' <= t    = Just x+  | otherwise       = Nothing  -- | Query a future value. Semantic function. future :: Future a -> Time -> Maybe a future (Future (extract -> t, x)) t'-  | t' >= t    = Just x-  | otherwise  = Nothing+  | Just t' >= t    = Just x+  | otherwise       = Nothing  -- TODO more elegant indexPast :: [Past a] -> Time -> Maybe a-indexPast ps t = firstTrue $ fmap (\p -> past p t) $ sortBy (comparing _onset) ps+indexPast ps t = firstTrue $ fmap (\p -> past p t) $ sortBy (comparing tv) ps+  where+    tv (Past (Min t, _)) = t  firstTrue :: [Maybe a] -> Maybe a firstTrue = listToMaybe . join . fmap maybeToList
+ src/Music/Time/Placed.hs view
@@ -0,0 +1,116 @@++{-# LANGUAGE DeriveDataTypeable         #-}+{-# LANGUAGE DeriveFoldable             #-}+{-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE DeriveTraversable          #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses      #-}+{-# LANGUAGE TypeFamilies               #-}+{-# LANGUAGE TypeOperators              #-}+{-# LANGUAGE RankNTypes                 #-}+{-# LANGUAGE TupleSections              #-}++-------------------------------------------------------------------------------------+-- |+-- Copyright   : (c) Hans Hoglund 2012-2014+--+-- License     : BSD-style+--+-- Maintainer  : hans@hanshoglund.se+-- Stability   : experimental+-- Portability : non-portable (TF,GNTD)+--+-------------------------------------------------------------------------------------++module Music.Time.Placed (+        -- * Placed type+        Placed,++        -- * Construction+        placed,+        placee,+  ) where++import           Control.Applicative+import           Control.Comonad+import           Control.Lens            hiding (Indexable, Level, above, below,+                                          index, inside, parts, reversed,+                                          transform, (<|), (|>))+import           Data.AffineSpace+import           Data.AffineSpace.Point+import           Data.Bifunctor+import           Data.Foldable           (Foldable)+import qualified Data.Foldable           as Foldable+import           Data.Functor.Adjunction (unzipR)+import           Data.Functor.Couple+import           Data.String+import           Data.Typeable+import           Data.VectorSpace++import           Music.Dynamics.Literal+import           Music.Pitch.Literal+import           Music.Time.Reverse+import           Music.Time.Split+++-- |+-- 'Placed' represents a value with an offset in time.+--+-- A placed value has a known 'position', but no 'duration'.+--+-- Placing a value inside 'Placed' does not make it invariant under 'stretch', as the+-- offset of a placed value may be stretched with respect to the origin. However, in+-- contrast to a note the /duration/ is not stretched.+--+newtype Placed a = Placed { getPlaced :: Time `Couple` a }+  deriving (+    Eq,+    Ord,+    Typeable,+    Foldable,+    Traversable,+    +    Functor,+    Applicative,+    Monad,+    Comonad    +    )++instance (Show a, Transformable a) => Show (Placed a) where+  show x = show (x^.from placed) ++ "^.placed"++instance Wrapped (Placed a) where+  type Unwrapped (Placed a) = (Time, a)+  _Wrapped' = iso (getCouple . getPlaced) (Placed . Couple)++instance Rewrapped (Placed a) (Placed b)++instance Transformable a => Transformable (Placed a) where+  transform t = +    over (from placed . _1) (transform t) +    . +    over (from placed . _2) (stretch $ stretchComponent t)++instance IsString a => IsString (Placed a) where+  fromString = pure . fromString++instance IsPitch a => IsPitch (Placed a) where+  fromPitch = pure . fromPitch++instance IsInterval a => IsInterval (Placed a) where+  fromInterval = pure . fromInterval++instance IsDynamics a => IsDynamics (Placed a) where+  fromDynamics = pure . fromDynamics++placed :: Iso (Time, a) (Time, b) (Placed a) (Placed b)+placed = _Unwrapped++placee :: (Transformable a, Transformable b) => Lens (Placed a) (Placed b) a b+placee = from placed `dependingOn` (transformed . delayingTime)+  where+    delayingTime = (>-> 1)++-- TODO consolidate+dependingOn :: Lens s t (x,a) (x,b) -> (x -> Lens a b c d) -> Lens s t c d+dependingOn l depending f = l (\ (x,a) -> (x,) <$> depending x f a)
src/Music/Time/Position.hs view
@@ -1,21 +1,17 @@  {-# LANGUAGE ConstraintKinds            #-} {-# LANGUAGE DeriveDataTypeable         #-}-{-# LANGUAGE DeriveFoldable             #-} {-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE DeriveFoldable             #-} {-# LANGUAGE DeriveTraversable          #-}-{-# LANGUAGE FlexibleContexts           #-}-{-# LANGUAGE FlexibleInstances          #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses      #-}-{-# LANGUAGE NoMonomorphismRestriction  #-} {-# LANGUAGE RankNTypes                 #-}-{-# LANGUAGE ScopedTypeVariables        #-} {-# LANGUAGE StandaloneDeriving         #-} {-# LANGUAGE TupleSections              #-} {-# LANGUAGE TypeFamilies               #-}-{-# LANGUAGE UndecidableInstances       #-} {-# LANGUAGE ViewPatterns               #-}+{-# LANGUAGE CPP                        #-}  ------------------------------------------------------------------------------------- -- |@@ -40,6 +36,8 @@        -- * Era       era,+      _onset,+      _offset,        -- * Position       position,@@ -57,10 +55,20 @@       stopAt,       placeAt, -      -- * Internal-      -- TODO hide...-      _setEra,-      _getEra,+      stretchRelative,+      stretchRelativeOnset,+      stretchRelativeMidpoint,+      stretchRelativeOffset,++      delayRelative,+      delayRelativeOnset,+      delayRelativeMidpoint,+      delayRelativeOffset,++      transformRelative,+      transformRelativeOnset,+      transformRelativeMidpoint,+      transformRelativeOffset,   ) where  @@ -102,38 +110,26 @@ -- @ -- class HasDuration a => HasPosition a where-  -- |-  -- Return the onset of the given value, or the value between the attack and decay phases.-  ---  _position :: a -> Duration -> Time-  _position x = alerp (_onset x) (_offset x) -  -- |-  -- Return the onset of the given value, or the value between the attack and decay phases.-  ---  _onset, _offset :: a -> Time-  _onset     = (`_position` 0)-  _offset    = (`_position` 1.0)--instance HasPosition Time where-  _position = const+  _position :: a -> Duration -> Time+  _position x = alerp a b where (a, b) = (_era x)^.range +  _era :: HasPosition a => a -> Span+  _era x = x `_position` 0 <-> x `_position` 1+   instance HasPosition Span where-  -- Override as an optimization:-  _onset    (view range -> (t1, t2)) = t1-  _offset   (view range -> (t1, t2)) = t2-  _position (view range -> (t1, t2)) = alerp t1 t2+  _era = id +#ifndef GHCI instance (HasPosition a, HasDuration a) => HasDuration [a] where   _duration x = _offset x .-. _onset x  instance (HasPosition a, HasDuration a) => HasPosition [a] where-  _onset  = foldr min 0 . fmap _onset-  _offset = foldr max 0 . fmap _offset--_getEra :: HasPosition a => a -> Span-_getEra x = _onset x <-> _offset x-{-# INLINE _getEra #-}+  _era x = (f x, g x)^.from range+    where+      f  = foldr min 0 . fmap _onset+      g = foldr max 0 . fmap _offset+#endif  -- | -- Position of the given value.@@ -208,6 +204,10 @@ placeAt :: (Transformable a, HasPosition a) => Duration -> Time -> a -> a placeAt p t x = (t .-. x `_position` p) `delay` x +_onset, _offset :: HasPosition a => a -> Time+_onset     = (`_position` 0)+_offset    = (`_position` 1.0)+ -- | -- Place a value over the given span. --@@ -220,7 +220,44 @@ -- A lens to the position -- era :: (HasPosition a, Transformable a) => Lens' a Span-era = lens _getEra (flip _setEra)+era = lens _era (flip _setEra) {-# INLINE era #-}++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  
src/Music/Time/Reactive.hs view
@@ -1,16 +1,13 @@  {-# LANGUAGE ConstraintKinds            #-} {-# LANGUAGE DeriveDataTypeable         #-}-{-# LANGUAGE DeriveFoldable             #-} {-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE DeriveFoldable             #-} {-# LANGUAGE DeriveTraversable          #-}-{-# LANGUAGE FlexibleInstances          #-}-{-# LANGUAGE GADTs                      #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses      #-}-{-# LANGUAGE NoMonomorphismRestriction  #-}-{-# LANGUAGE ScopedTypeVariables        #-}-{-# LANGUAGE TemplateHaskell            #-}+{-# LANGUAGE StandaloneDeriving         #-}+{-# LANGUAGE TupleSections              #-} {-# LANGUAGE TypeFamilies               #-} {-# LANGUAGE ViewPatterns               #-} @@ -70,7 +67,7 @@  import           Music.Time.Behavior import           Music.Time.Bound-import           Music.Time.Note+import           Music.Time.Event import           Music.Time.Reverse import           Music.Time.Segment import           Music.Time.Split@@ -119,6 +116,9 @@ instance Transformable (Reactive a) where     transform s (Reactive (t,r)) = Reactive (transform s t, transform s r) +instance Reversible (Reactive a) where+  rev = stretch (-1)+ instance Wrapped (Reactive a) where     type Unwrapped (Reactive a) = ([Time], Behavior a)     _Wrapped' = iso getReactive Reactive@@ -126,7 +126,12 @@ instance Rewrapped (Reactive a) (Reactive b) instance Applicative Reactive where     pure  = pureDefault+      where+        pureDefault = view _Unwrapped . pure . pure+             (<*>) = apDefault+      where+        (view _Wrapped -> (tf, rf)) `apDefault` (view _Wrapped -> (tx, rx)) = view _Unwrapped (tf <> tx, rf <*> rx)  instance IsPitch a => IsPitch (Reactive a) where   fromPitch = pure . fromPitch@@ -146,8 +151,6 @@     diminish = fmap diminish  -(view _Wrapped -> (tf, rf)) `apDefault` (view _Wrapped -> (tx, rx)) = view _Unwrapped (tf <> tx, rf <*> rx)-pureDefault = view _Unwrapped . pure . pure  -- | -- Get the initial value.@@ -171,16 +174,16 @@ occs :: Reactive a -> [Time] occs = fst . (^. _Wrapped') --- | Split a reactive into notes, as well as the values before and after the first/last update-splitReactive :: Reactive a -> Either a ((a, Time), [Note a], (Time, a))+-- | Split a reactive into events, as well as the values before and after the first/last update+splitReactive :: Reactive a -> Either a ((a, Time), [Event a], (Time, a)) splitReactive r = case updates r of     []          -> Left  (initial r)     (t,x):[]    -> Right ((initial r, t), [], (t, x))-    (t,x):xs    -> Right ((initial r, t), fmap mkNote $ mrights (res $ (t,x):xs), head $ mlefts (res $ (t,x):xs))+    (t,x):xs    -> Right ((initial r, t), fmap mkEvent $ mrights (res $ (t,x):xs), head $ mlefts (res $ (t,x):xs))      where -        mkNote (t,u,x) = (t <-> u, x)^.note+        mkEvent (t,u,x) = (t <-> u, x)^.event          -- Always returns a 0 or more Right followed by one left         res :: [(Time, a)] -> [Either (Time, a) (Time, Time, a)]@@ -198,11 +201,6 @@                 go [x]      = [(x, Nothing)]                 go (x:y:rs) = (x, Just y) : withNext (y : rs) -{-# DEPRECATED updates "" #-}-{-# DEPRECATED occs "" #-}-{-# DEPRECATED splitReactive "" #-}-{-# DEPRECATED atTime "" #-}- atTime :: Reactive a -> Time -> a atTime = (!) . snd . (^. _Wrapped') @@ -224,9 +222,9 @@ -- | -- Get all intermediate values. ---intermediate :: Transformable a => Reactive a -> [Note a]+intermediate :: Transformable a => Reactive a -> [Event a] intermediate (updates -> []) = []-intermediate (updates -> xs) = fmap (\((t1, x), (t2, _)) -> (t1 <-> t2, x)^.note) $ withNext $ xs+intermediate (updates -> xs) = fmap (\((t1, x), (t2, _)) -> (t1 <-> t2, x)^.event) $ withNext $ xs   where     withNext xs = zip xs (tail xs) @@ -236,24 +234,14 @@ discrete :: Reactive a -> Behavior a discrete = continous . fmap pure --- |--- Realize a 'Reactive' value as an continous behavior.------ See also 'concatSegment' and 'concatB'.---+-- | Realize a 'Reactive' value as an continous behavior. continous :: Reactive (Segment a) -> Behavior a --- |--- Realize a 'Reactive' value as an continous behavior.------ See also 'concatSegment' and 'concatB'.---+-- | Realize a 'Reactive' value as an continous behavior. continousWith :: Segment (a -> b) -> Reactive a -> Behavior b continousWith f x = continous $ liftA2 (<*>) (pure f) (fmap pure x) --- |--- Sample a 'Behavior' into a reactive.---+-- | Sample a 'Behavior' into a reactive. sample   :: [Time] -> Behavior a -> Reactive a  -- TODO linear approximation@@ -298,5 +286,4 @@ newtype Search a = Search { getSearch :: forall r . (a -> Tree r) -> Tree r }    -} --- JUNK 
src/Music/Time/Reverse.hs view
@@ -1,20 +1,15 @@  {-# LANGUAGE ConstraintKinds            #-} {-# LANGUAGE DeriveDataTypeable         #-}-{-# LANGUAGE DeriveFoldable             #-} {-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE DeriveFoldable             #-} {-# LANGUAGE DeriveTraversable          #-}-{-# LANGUAGE FlexibleContexts           #-}-{-# LANGUAGE FlexibleInstances          #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses      #-}-{-# LANGUAGE NoMonomorphismRestriction  #-}-{-# LANGUAGE RankNTypes                 #-}-{-# LANGUAGE ScopedTypeVariables        #-} {-# LANGUAGE StandaloneDeriving         #-} {-# LANGUAGE TupleSections              #-} {-# LANGUAGE TypeFamilies               #-}-{-# LANGUAGE UndecidableInstances       #-}+{-# LANGUAGE ViewPatterns               #-}  ------------------------------------------------------------------------------------- -- |@@ -165,9 +160,11 @@ -- A default implementation of 'rev' -- revDefault :: (HasPosition a, Transformable a) => a -> a--- revDefault x = (stretch (-1) `whilst` undelaying (_position x 0.5 .-. 0)) x revDefault x = stretch (-1) x +-- Alternative:+-- revDefault x = (stretch (-1) `whilst` undelaying (_position x 0.5 .-. 0)) x+--   where f `whilst` t = over (transformed t) f  newtype NoReverse a = NoReverse { getNoReverse :: a }   deriving (Typeable, Eq, Ord, Show)@@ -186,87 +183,4 @@ -- reversed :: Reversible a => Iso' a a reversed = iso rev rev------{---- |--- Reversible values.------ For instances of 'Reversible' and 'HasOnset', the following laws should hold:------ > onset a    = onset (rev a)--- > duration a = duration (rev a)------ For structural types, 'rev' is applied recursively, hence the constraint on--- the 'Score' instance. 'rev' is id by default, so for a trivial type @T@ it--- suffices to write------ > instance Reversible T------ For instances 'U' of 'HasOnset' and 'Transformable', a suitable instance--- is------ > instance Reversible T where--- >     rev = withSameOnset (stretch (-1))--------class Reversible a where--    -- |-    -- Reverse a value.-    ---    -- Reverse is an involution, meaning that:-    ---    -- > rev (rev a) = a-    ---    rev :: a -> a-    rev = id---- instance Reversible Time where-    -- rev t = mirror t--instance Reversible Double-instance Reversible Float-instance Reversible Int-instance Reversible Integer-instance Reversible ()-instance Reversible (Ratio a)--instance Reversible a => Reversible [a] where-    rev = fmap rev--instance (Ord a, Reversible a) => Reversible (Set a) where-    rev = Set.map rev--instance Reversible a => Reversible (Map k a) where-    rev = fmap rev--newtype NoRev a = NoRev { getNoRev :: a }-    deriving (Eq, Ord, Enum, Show, Semigroup, Monoid,-        Delayable, Stretchable, HasOnset, HasOffset, HasDuration)--instance Reversible (NoRev a) where-    rev = id----newtype WithRev a = WithRev (a,a)-    deriving (Eq, Ord, Semigroup, Monoid)--withRev :: Reversible a => a -> WithRev a-withRev x = WithRev (rev x, x)--fromWithRev :: Reversible a => WithRev a -> a-fromWithRev (WithRev (_,x)) = x--instance Reversible a => Reversible (WithRev a) where-    rev (WithRev (r,x)) = WithRev (x,r)---- JUNK-                                         -}- 
src/Music/Time/Score.hs view
@@ -1,20 +1,14 @@  {-# LANGUAGE ConstraintKinds            #-} {-# LANGUAGE DeriveDataTypeable         #-}-{-# LANGUAGE DeriveFoldable             #-} {-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE DeriveFoldable             #-} {-# LANGUAGE DeriveTraversable          #-}-{-# LANGUAGE FlexibleContexts           #-}-{-# LANGUAGE FlexibleInstances          #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses      #-}-{-# LANGUAGE NoMonomorphismRestriction  #-}-{-# LANGUAGE RankNTypes                 #-}-{-# LANGUAGE ScopedTypeVariables        #-} {-# LANGUAGE StandaloneDeriving         #-} {-# LANGUAGE TupleSections              #-} {-# LANGUAGE TypeFamilies               #-}-{-# LANGUAGE UndecidableInstances       #-} {-# LANGUAGE ViewPatterns               #-}  -------------------------------------------------------------------------------------@@ -37,22 +31,21 @@          -- * Construction         score,-        notes,-        eras,         events,-        singleNote,+        eras,+        triples,          -- * Traversal         mapWithSpan,         filterWithSpan,         mapFilterWithSpan,-        mapEvents,-        filterEvents,-        mapFilterEvents,+        mapTriples,+        filterTriples,+        mapFilterTriples,          -- * Simultaneous         -- TODO check for overlapping values etc-        simult,+        -- simult,         simultaneous,          -- * Normalize@@ -60,8 +53,8 @@         printEras,          -- * Unsafe versions-        unsafeNotes,         unsafeEvents,+        unsafeTriples,            ) where @@ -80,10 +73,10 @@  import           Music.Time.Juxtapose   (scat) import           Music.Time.Meta-import           Music.Time.Note+import           Music.Time.Event import           Music.Time.Reverse import           Music.Time.Split-import           Music.Time.Stretched+import           Music.Time.Note import           Music.Time.Voice  import           Control.Applicative@@ -109,8 +102,6 @@   -type ScoreNote a = Note a- --   * 'empty' creates an empty score -- --   * 'pure' creates a score containing a single note in the span @0 '<->' 1@@@ -124,30 +115,24 @@ -- You can also use '<>' and 'mempty' of course. -- --- |--- A 'Score' is a sequential or parallel composition of values, and allows overlapping events+-- | A 'Score' is a sequential or parallel composition of values, and allows overlapping events+newtype Score a = Score { getScore :: (Meta, Score' a) }+    deriving (Functor, Semigroup, Monoid, Foldable, Traversable, Typeable{-, Show, Eq, Ord-})+ ----- You typically create a 'Score' using 'score', 'notes', 'voices', and 'phrases', or the 'Alternative' interface.+-- You typically create a 'Score' using 'score', 'events', 'voices', and 'phrases', or the 'Alternative' interface. -- -- Score is an instance of 'Transformable', so you can use 'delay' and 'stretch'. -- -- Score is an instance of 'HasPosition', so you can use 'duration', 'onset', 'offset', 'era'. ----- To inspect or deconstruct a score, see 'notes', 'voices', and 'phrases', as+-- To inspect or deconstruct a score, see 'events', 'voices', and 'phrases', as -- well as 'singleNote', 'singleVoice', and 'singlePhrase' ---newtype Score a = Score { getScore' :: (Meta, NScore a) }-    deriving (Functor, Semigroup, Monoid, Foldable, Traversable, Typeable{-, Show, Eq, Ord-}) ------ $semantics Score------ type Score a = [Note a]---- instance Wrapped (Score a) where-  type Unwrapped (Score a) = (Meta, NScore a)-  _Wrapped' = iso getScore' Score+  type Unwrapped (Score a) = (Meta, Score' a)+  _Wrapped' = iso getScore Score  instance Rewrapped (Score a) (Score b) where @@ -181,18 +166,18 @@ instance Transformable (Score a) where   transform t (Score (m,x)) = Score (transform t m, transform t x) -instance Reversible a => Reversible (Score a) where-  rev (Score (m,x)) = Score (rev m, rev x)+-- instance Reversible a => Reversible (Score a) where+  -- rev (Score (m,x)) = Score (rev m, rev x) -instance Splittable a => Splittable (Score a) where-  split t (Score (m,x)) = (Score (m1,x1), Score (m2,x2))-    where-      (m1, m2) = split t m-      (x1, x2) = split t x+-- instance Splittable a => Splittable (Score a) where+  -- split t (Score (m,x)) = (Score (m1,x1), Score (m2,x2))+    -- where+      -- (m1, m2) = split t m+      -- (x1, x2) = split t x --- TODO move these two "implementations" to NScore+-- TODO move these two "implementations" to Score' instance HasPosition (Score a) where-  _position = _position . snd . view _Wrapped' . normalizeScore'+  _position = _position . snd . view _Wrapped' {-. normalizeScore'-}   -- TODO clean up in terms of AddMeta and optimize  instance HasDuration (Score a) where@@ -247,204 +232,108 @@   -newtype NScore a = NScore { getNScore :: [ScoreNote a] }+newtype Score' a = Score' { getScore' :: [Event a] }   deriving ({-Eq, -}{-Ord, -}{-Show, -}Functor, Foldable, Traversable, Semigroup, Monoid, Typeable, Show, Eq)  instance (Show a, Transformable a) => Show (Score a) where-  show x = show (x^.notes) ++ "^.score"+  show x = show (x^.events) ++ "^.score" -instance Wrapped (NScore a) where-  type Unwrapped (NScore a) = [ScoreNote a]-  _Wrapped' = iso getNScore NScore+instance Wrapped (Score' a) where+  type Unwrapped (Score' a) = [Event a]+  _Wrapped' = iso getScore' Score' -instance Rewrapped (NScore a) (NScore b)+instance Rewrapped (Score' a) (Score' b) -instance Applicative NScore where+instance Applicative Score' where   pure  = return   (<*>) = ap -instance Monad NScore where+instance Monad Score' where   return = (^. _Unwrapped) . pure . pure   xs >>= f = (^. _Unwrapped) $ mbind ((^. _Wrapped') . f) ((^. _Wrapped') xs) -instance Alternative NScore where+instance Alternative Score' where   empty = mempty   (<|>) = mappend -instance MonadPlus NScore where+instance MonadPlus Score' where   mzero = mempty   mplus = mappend -{--instance FunctorWithIndex Span NScore where-  imap = undefined-  -- TODO--instance FoldableWithIndex Span NScore where-  ifoldMap = undefined-  -- TODO--instance TraversableWithIndex Span NScore where-  itraverse = undefined-  -- TODO--}--instance Transformable (NScore a) where-  transform t (NScore xs) = NScore (fmap (transform t) xs)--instance Reversible a => Reversible (NScore a) where-  rev (NScore xs) = NScore (fmap rev xs)--instance HasPosition (NScore a) where-  _onset  = safeMinimum . fmap _onset . view _Wrapped'-  _offset = safeMaximum . fmap _offset . view _Wrapped'---- TODO move-safeMinimum xs = if null xs then 0 else minimum xs-safeMaximum xs = if null xs then 0 else maximum xs+instance Transformable (Score' a) where+  transform t = over (_Wrapped) (transform t) -instance HasDuration (NScore a) where-  _duration x = _offset x .-. _onset x+-- instance Reversible a => Reversible (Score' a) where+--   rev (Score' xs) = Score' (fmap rev xs) -instance Splittable a => Splittable (NScore a) where-  split t (NScore notes) = over both (NScore . mfilter (not . isEmptyNote)) $ unzip $ map (\x -> splitAbs (0 .+^ t) x) notes+instance HasPosition (Score' a) where+  _era x = (f x, g x)^.from range     where-      -- TODO move-      isEmptyNote :: Note a -> Bool-      isEmptyNote = isEmptySpan . view era-      -      isEmptySpan :: Span -> Bool-      isEmptySpan (view range -> (t, u)) = t == u+      f = safeMinimum . fmap (_onset  . normalizeSpan) . toListOf (_Wrapped . each . era)+      g = safeMaximum . fmap (_offset . normalizeSpan) . toListOf (_Wrapped . each . era)+      safeMinimum xs = if null xs then 0 else minimum xs+      safeMaximum xs = if null xs then 0 else maximum xs +instance HasDuration (Score' a) where+  _duration x = _offset x .-. _onset x --- |--- Create a score from a list of notes.------ This is a getter (rather than a function) for consistency:------ @--- [ (0 '<->' 1, 10)^.'note',---   (1 '<->' 2, 20)^.'note',---   (3 '<->' 4, 30)^.'note' ]^.'score'--- @------ @--- 'view' 'score' $ 'map' ('view' 'note') [(0 '<->' 1, 1)]--- @------ Se also 'notes'.----score :: Getter [Note a] (Score a)-score = from unsafeNotes+-- | Create a score from a list of events.+score :: Getter [Event a] (Score a)+score = from unsafeEvents {-# INLINE score #-} --- |--- View a 'Score' as a list of 'Note' values.+-- | View a 'Score' as a list of 'Event' values.+events :: Lens (Score a) (Score b) [Event a] [Event b]+events = _Wrapped . _2 . _Wrapped . sorted+  where+    -- TODO should not have to sort...+    sorted = iso (List.sortBy (Ord.comparing _onset)) (List.sortBy (Ord.comparing _onset))+{-# INLINE events #-}+ -- -- @--- 'view' 'notes'                        :: 'Score' a -> ['Note' a]--- 'set'  'notes'                        :: ['Note' a] -> 'Score' a -> 'Score' a--- 'over' 'notes'                        :: (['Note' a] -> ['Note' b]) -> 'Score' a -> 'Score' b+-- 'view' 'events'                        :: 'Score' a -> ['Event' a]+-- 'set'  'events'                        :: ['Event' a] -> 'Score' a -> 'Score' a+-- 'over' 'events'                        :: (['Event' a] -> ['Event' b]) -> 'Score' a -> 'Score' b -- @ -- -- @--- 'preview'  ('notes' . 'each')           :: 'Score' a -> 'Maybe' ('Note' a)--- 'preview'  ('notes' . 'element' 1)      :: 'Score' a -> 'Maybe' ('Note' a)--- 'preview'  ('notes' . 'elements' odd)   :: 'Score' a -> 'Maybe' ('Note' a)+-- 'preview'  ('events' . 'each')           :: 'Score' a -> 'Maybe' ('Event' a)+-- 'preview'  ('events' . 'element' 1)      :: 'Score' a -> 'Maybe' ('Event' a)+-- 'preview'  ('events' . 'elements' odd)   :: 'Score' a -> 'Maybe' ('Event' a) -- @ -- -- @--- 'set'      ('notes' . 'each')           :: 'Note' a -> 'Score' a -> 'Score' a--- 'set'      ('notes' . 'element' 1)      :: 'Note' a -> 'Score' a -> 'Score' a--- 'set'      ('notes' . 'elements' odd)   :: 'Note' a -> 'Score' a -> 'Score' a+-- 'set'      ('events' . 'each')           :: 'Event' a -> 'Score' a -> 'Score' a+-- 'set'      ('events' . 'element' 1)      :: 'Event' a -> 'Score' a -> 'Score' a+-- 'set'      ('events' . 'elements' odd)   :: 'Event' a -> 'Score' a -> 'Score' a -- @ -- -- @--- 'over'     ('notes' . 'each')           :: ('Note' a -> 'Note' b) -> 'Score' a -> 'Score' b--- 'over'     ('notes' . 'element' 1)      :: ('Note' a -> 'Note' a) -> 'Score' a -> 'Score' a--- 'over'     ('notes' . 'elements' odd)   :: ('Note' a -> 'Note' a) -> 'Score' a -> 'Score' a+-- 'over'     ('events' . 'each')           :: ('Event' a -> 'Event' b) -> 'Score' a -> 'Score' b+-- 'over'     ('events' . 'element' 1)      :: ('Event' a -> 'Event' a) -> 'Score' a -> 'Score' a+-- 'over'     ('events' . 'elements' odd)   :: ('Event' a -> 'Event' a) -> 'Score' a -> 'Score' a -- @ -- -- @--- 'toListOf' ('notes' . 'each')                :: 'Score' a -> ['Note' a]--- 'toListOf' ('notes' . 'elements' odd)        :: 'Score' a -> ['Note' a]--- 'toListOf' ('notes' . 'each' . 'filtered'---              (\\x -> '_duration' x \< 2))  :: 'Score' a -> ['Note' a]+-- 'toListOf' ('events' . 'each')                :: 'Score' a -> ['Event' a]+-- 'toListOf' ('events' . 'elements' odd)        :: 'Score' a -> ['Event' a]+-- 'toListOf' ('events' . 'each' . 'filtered'+--              (\\x -> '_duration' x \< 2))  :: 'Score' a -> ['Event' a] -- @------ This is not an 'Iso', as the note list representation does not contain meta-data.--- To construct a score from a note list, use 'score' or @'flip' ('set' 'notes') 'empty'@.----notes :: Lens (Score a) (Score b) [Note a] [Note b]-notes = _Wrapped . _2 . _Wrapped . sorted-  where-    sorted = iso (List.sortBy (Ord.comparing _onset)) (List.sortBy (Ord.comparing _onset))--- notes = unsafeNotes-{-# INLINE notes #-} --- -- |--- -- View a score as a list of voices.--- ----- -- @--- -- 'view' 'voices'                        :: 'Score' a -> ['Voice' a]--- -- 'set'  'voices'                        :: ['Voice' a] -> 'Score' a -> 'Score' a--- -- 'over' 'voices'                        :: (['Voice' a] -> ['Voice' b]) -> 'Score' a -> 'Score' b--- -- @--- ----- -- @--- -- 'preview'  ('voices' . 'each')           :: 'Score' a -> 'Maybe' ('Voice' a)--- -- 'preview'  ('voices' . 'element' 1)      :: 'Score' a -> 'Maybe' ('Voice' a)--- -- 'preview'  ('voices' . 'elements' odd)   :: 'Score' a -> 'Maybe' ('Voice' a)--- -- @--- ----- -- @--- -- 'set'      ('voices' . 'each')           :: 'Voice' a -> 'Score' a -> 'Score' a--- -- 'set'      ('voices' . 'element' 1)      :: 'Voice' a -> 'Score' a -> 'Score' a--- -- 'set'      ('voices' . 'elements' odd)   :: 'Voice' a -> 'Score' a -> 'Score' a--- -- @--- ----- -- @--- -- 'over'     ('voices' . 'each')           :: ('Voice' a -> 'Voice' b) -> 'Score' a -> 'Score' b--- -- 'over'     ('voices' . 'element' 1)      :: ('Voice' a -> 'Voice' a) -> 'Score' a -> 'Score' a--- -- 'over'     ('voices' . 'elements' odd)   :: ('Voice' a -> 'Voice' a) -> 'Score' a -> 'Score' a--- -- @--- ----- -- @--- -- 'toListOf' ('voices' . 'each')           :: 'Score' a -> ['Voice' a]--- -- 'toListOf' ('voices' . 'elements' odd)   :: 'Score' a -> ['Voice' a]--- -- 'toListOf' ('voices' . 'each' . 'filtered' (\\x -> '_duration' x \< 2)) :: 'Score' a -> ['Voice' a]--- -- @--- ----- -- This is not an 'Iso', as the voice list representation does not contain meta-data.--- -- To construct a score from a voice list, use 'score' or @'flip' ('set' 'voices') 'empty'@.--- ----- voices :: Lens (Score a) (Score b) [Voice a] [Voice b]--- voices = unsafeVoices--- {-# INLINE voices #-}---- |--- View a score as a list of notes.------ This only an isomorphism up to meta-data. See also the safe (but more restricted)--- 'notes' and 'score'.----unsafeNotes :: Iso (Score a) (Score b) [Note a] [Note b]-unsafeNotes = _Wrapped . noMeta . _Wrapped . sorted+-- | A score is a list of events up to meta-data. To preserve meta-data, use the more+-- restricted 'score' and 'events'.+unsafeEvents :: Iso (Score a) (Score b) [Event a] [Event b]+unsafeEvents = _Wrapped . noMeta . _Wrapped . sorted   where     sorted = iso (List.sortBy (Ord.comparing _onset)) (List.sortBy (Ord.comparing _onset))     noMeta = iso extract return-    -- noMeta = iso (\(_,x) -> x) (\x -> (mempty,x)) -{-# INLINE unsafeNotes #-}---- |--- View a score as a list of events.------ This only an isomorphism up to meta-data. See also the safe (but more restricted)--- 'notes' and 'score'.----unsafeEvents :: Iso (Score a) (Score b) [(Time, Duration, a)] [(Time, Duration, b)]-unsafeEvents = iso _getScore _score+-- | A score is a list of (time-duration-value triples) up to meta-data.+-- To preserve meta-data, use the more restricted 'triples'.+unsafeTriples :: Iso (Score a) (Score b) [(Time, Duration, a)] [(Time, Duration, b)]+unsafeTriples = iso _getScore _score   where     _score :: [(Time, Duration, a)] -> Score a     _score = mconcat . fmap (uncurry3 event)@@ -456,91 +345,61 @@       fmap (\(view delta -> (t,d),x) -> (t,d,x)) .       List.sortBy (Ord.comparing fst) .       Foldable.toList .-      fmap (view $ from note) .+      fmap (view $ from event) .       reifyScore     ----- |--- View a score as a single note.----singleNote :: Prism' (Score a) (Note a)-singleNote = unsafeNotes . single-{-# INLINE singleNote #-}-{-# DEPRECATED singleNote "Use 'unsafeNotes . single'" #-}--- TODO make prism fail if score contains meta-data--- (or else second prism law is not satisfied)-- -- | Map with the associated time span.-mapScore :: (Note a -> b) -> Score a -> Score b-mapScore f = over (_Wrapped._2) (mapNScore f)+mapScore :: (Event a -> b) -> Score a -> Score b+mapScore f = over (_Wrapped._2) (mapScore' f)   where-    mapNScore f = over (_Wrapped.traverse) (extend f)+    mapScore' f = over (_Wrapped.traverse) (extend f) -reifyScore :: Score a -> Score (Note a)+reifyScore :: Score a -> Score (Event a) reifyScore = over (_Wrapped . _2 . _Wrapped) $ fmap duplicate --- |--- View a score as a list of events, i.e. time-duration-value triplets.------ This is a convenient combination of 'notes' and 'event'.------ @--- 'events' = 'notes' . 'through' 'event' 'event'--- @----events :: {-Transformable a => -}Lens (Score a) (Score b) [(Time, Duration, a)] [(Time, Duration, b)]-events = notes . through event event-+-- | View a score as a list of time-duration-value triplets.+triples :: {-Transformable a => -}Lens (Score a) (Score b) [(Time, Duration, a)] [(Time, Duration, b)]+triples = events . _zipList . through triple triple . from _zipList   -- | Map over the values in a score. mapWithSpan :: (Span -> a -> b) -> Score a -> Score b-mapWithSpan f = mapScore (uncurry f . view (from note))+mapWithSpan f = mapScore (uncurry f . view (from event))  -- | Filter the values in a score. filterWithSpan :: (Span -> a -> Bool) -> Score a -> Score a filterWithSpan f = mapFilterWithSpan (partial2 f) --- | Combination of 'mapEvents' and 'filterEvents'.+-- | Combination of 'mapTriples' and 'filterTriples'. mapFilterWithSpan :: (Span -> a -> Maybe b) -> Score a -> Score b mapFilterWithSpan f = mcatMaybes . mapWithSpan f  -- | Map over the values in a score.-mapEvents :: (Time -> Duration -> a -> b) -> Score a -> Score b-mapEvents f = mapWithSpan (uncurry f . view delta)+mapTriples :: (Time -> Duration -> a -> b) -> Score a -> Score b+mapTriples f = mapWithSpan (uncurry f . view delta)  -- | Filter the values in a score.-filterEvents   :: (Time -> Duration -> a -> Bool) -> Score a -> Score a-filterEvents f = mapFilterEvents (partial3 f)+filterTriples   :: (Time -> Duration -> a -> Bool) -> Score a -> Score a+filterTriples f = mapFilterTriples (partial3 f) --- | Efficient combination of 'mapEvents' and 'filterEvents'.-mapFilterEvents :: (Time -> Duration -> a -> Maybe b) -> Score a -> Score b-mapFilterEvents f = mcatMaybes . mapEvents f+-- | Efficient combination of 'mapTriples' and 'filterTriples'.+mapFilterTriples :: (Time -> Duration -> a -> Maybe b) -> Score a -> Score b+mapFilterTriples f = mcatMaybes . mapTriples f --- | Mainly useful for backends.+-- | Normalize a score, assuring its events spans are all forward (as by 'isForwardSpan'),+-- and that its onset is at least zero. Consequently, the onset and offset of each event+-- in the score is at least zero. normalizeScore :: Score a -> Score a-normalizeScore = reset . normalizeScore'+normalizeScore = reset . normalizeScoreDurations   where     reset x = set onset (view onset x `max` 0) x+    normalizeScoreDurations = over (events . each . era) normalizeSpan -normalizeScore' = over (notes . each . era) normalizeSpan -- TODO version that reverses the values where appropriate--- Use over (notes . each) normalizeNote or similar---- normalizeScore = reset . absDurations---   where---     reset x = set onset (view onset x `max` 0) x---     absDurations = over (notes.each.era.delta._2) abs+-- Use over (events . each) normalizeEvent or similar  -- |--- Extract all eras of the given score.------ >>> printEras $ scat [c,d,e :: Score Integer]--- 0 <-> 1--- 1 <-> 2--- 2 <-> 3+-- Print the span of each event, as given by 'eras'. -- printEras :: Score a -> IO () printEras = mapM_ print . toListOf eras@@ -552,15 +411,15 @@ -- [0 <-> 1,1 <-> 2,2 <-> 3] -- eras :: Traversal' (Score a) Span-eras = notes . each . era+eras = events . each . era +-- TODO rename and expose this+-- We have an (Iso (Score a) (TMap Span [a])), with [] as default value chordEvents :: Transformable a => Span -> Score a -> [a]-chordEvents s = fmap extract . filter ((== s) . view era) . view notes--+chordEvents s = fmap extract . filter ((== s) . view era) . view events  simultaneous' :: Transformable a => Score a -> Score [a]-simultaneous' sc = (^. from unsafeEvents) vs+simultaneous' sc = (^. from unsafeTriples) vs   where     -- es :: [Era]     -- evs :: [[a]]@@ -572,18 +431,7 @@ -- overSimult :: Transformable a => (Score [a] -> Score [b]) -> Score a -> Score b -- overSimult f = mscatter . f . simultaneous' --- |--- Merge all simultaneous events using their 'Semigroup' instance.------ Two events /a/ and /b/ are considered simultaneous if and only if they have the same--- era, that is if @`era` a == `era` b@---+-- | Merge all simultaneous events using their 'Semigroup' instance. simultaneous :: (Transformable a, Semigroup a) => Score a -> Score a simultaneous = fmap (sconcat . NonEmpty.fromList) . simultaneous' -simult :: Transformable a => Lens (Score a) (Score b) (Score [a]) (Score [b])-simult = iso simultaneous' mscatter--- TODO identical to: lens simultaneous' (flip $ mapSimultaneous . const)--- wrap in something to preserve meta---- JUNK
src/Music/Time/Segment.hs view
@@ -1,20 +1,14 @@  {-# LANGUAGE ConstraintKinds            #-} {-# LANGUAGE DeriveDataTypeable         #-}-{-# LANGUAGE DeriveFoldable             #-} {-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE DeriveFoldable             #-} {-# LANGUAGE DeriveTraversable          #-}-{-# LANGUAGE FlexibleContexts           #-}-{-# LANGUAGE FlexibleInstances          #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses      #-}-{-# LANGUAGE NoMonomorphismRestriction  #-}-{-# LANGUAGE RankNTypes                 #-}-{-# LANGUAGE ScopedTypeVariables        #-} {-# LANGUAGE StandaloneDeriving         #-} {-# LANGUAGE TupleSections              #-} {-# LANGUAGE TypeFamilies               #-}-{-# LANGUAGE UndecidableInstances       #-} {-# LANGUAGE ViewPatterns               #-}  -------------------------------------------------------------------------------------@@ -100,11 +94,11 @@  import           Music.Time.Behavior import           Music.Time.Bound-import           Music.Time.Note+import           Music.Time.Event import           Music.Time.Reverse import           Music.Time.Score import           Music.Time.Split-import           Music.Time.Stretched+import           Music.Time.Note import           Music.Time.Voice  import           Control.Applicative@@ -127,9 +121,9 @@ -- A 'Segment' is a value varying over some unknown time span.  -- Intuitively, a 'Segment' is to a 'Behavior' what a /ray/ is to a /line/. ----- To give a segment an explicit duration, use 'Stretched' 'Segment'.+-- To give a segment an explicit duration, use 'Event' 'Segment'. ----- To place a segment in a particular time span, use 'Note' 'Segment'.+-- To place a segment in a particular time span, use 'Event' 'Segment'. -- newtype Segment a = Segment { getSegment :: Clipped Duration -> a }   deriving (Functor, Applicative, Monad{-, Comonad-}, Typeable)@@ -143,9 +137,9 @@  -- $musicTimeSegmentExamples ----- > foldr1 apSegments' $ map (view stretched) $ [(0.5,0::Segment Float), (1, timeS), (2,rev timeS), (3,-1)]+-- > foldr1 apSegments' $ map (view note) $ [(0.5,0::Segment Float), (1, timeS), (2,rev timeS), (3,-1)] ----- > openG $ draw $ (1, timeS :: Segment Float)^.stretched+-- > openG $ draw $ (1, timeS :: Segment Float)^.note --  instance Show (Segment a) where@@ -207,7 +201,6 @@ -- instance (HasPart a a, HasPart a b) => HasPart (Segment a) (Segment b) where --   part = through part part --- #ifdef INCLUDE_LIFTED -- deriving instance Semigroup a => Semigroup (Segment a) -- deriving instance Monoid a => Monoid (Segment a) -- deriving instance Num a => Num (Segment a)@@ -235,7 +228,6 @@ --   (<) = error "No fun" --   max = liftA2 max --   min = liftA2 min--- #endif  -- | -- View a segment as a time function and vice versa.@@ -243,15 +235,15 @@ segment :: Iso (Duration -> a) (Duration -> b) (Segment a) (Segment b) segment = R.tabulated -apSegments' :: Stretched (Segment a) -> Stretched (Segment a) -> Stretched (Segment a)-apSegments' (view (from stretched) -> (d1,s1)) (view (from stretched) -> (d2,s2))-  = view stretched (d1+d2, slerp (d1/(d1+d2)) s1 s2)+apSegments' :: Note (Segment a) -> Note (Segment a) -> Note (Segment a)+apSegments' (view (from note) -> (d1,s1)) (view (from note) -> (d2,s2))+  = view note (d1+d2, slerp (d1/(d1+d2)) s1 s2)  -- |--- Append a voice of segments to a single stretched segment.+-- Append a voice of segments to a single note segment. ---apSegments :: Voice (Segment a) -> Stretched (Segment a)-apSegments = foldr1 apSegments' . toListOf (stretcheds . each)+apSegments :: Voice (Segment a) -> Note (Segment a)+apSegments = foldr1 apSegments' . toListOf (notes . each)  -- t < i && 0 <= t <= 1   ==> 0 < (t/i) < 1 -- i     is the fraction of the slerped segment spent in a@@ -271,30 +263,30 @@   -- |--- View a 'Note' 'Segment' as a 'Bound' 'Behavior' and vice versa.+-- View a 'Event' 'Segment' as a 'Bound' 'Behavior' and vice versa. -- -- This can be used to safely turn a behavior into a segment and vice -- versa. Often 'focusing' is more convenient to use. ---bounded' :: Iso' (Note (Segment a)) (Bound (Behavior a))+bounded' :: Iso' (Event (Segment a)) (Bound (Behavior a)) bounded' = bounded  -- |--- View a 'Note' 'Segment' as a 'Bound' 'Behavior' and vice versa.+-- View a 'Event' 'Segment' as a 'Bound' 'Behavior' and vice versa. -- -- This can be used to safely turn a behavior into a segment and vice -- versa. Often 'focusing' is more convenient to use. ---bounded :: Iso (Note (Segment a)) (Note (Segment b)) (Bound (Behavior a)) (Bound (Behavior b))+bounded :: Iso (Event (Segment a)) (Event (Segment b)) (Bound (Behavior a)) (Bound (Behavior b)) bounded = iso ns2bb bb2ns   where-    bb2ns (Bound (s, x)) = view note (s, b2s $ transform (negateV s) $ x)-    ns2bb (view (from note) -> (s, x)) = Bound (s,       transform s           $ s2b $ x)+    bb2ns (Bound (s, x)) = view event (s, b2s $ transform (negateV s) $ x)+    ns2bb (view (from event) -> (s, x)) = Bound (s,       transform s           $ s2b $ x)     s2b = under R.tabulated (. realToFrac)     b2s = under R.tabulated (. realToFrac)  ----- Note that the isomorhism only works because of 'Bound' being abstract.+-- Event that the isomorhism only works because of 'Bound' being abstract. -- A function @unBound :: Bound a -> a@ could break the isomorphism -- as follows: --@@ -336,7 +328,7 @@     -- fromJust is safe here, as toLast is used to create the Maybe wrapper  -concatSegment :: Monoid a => Note (Segment a) -> Behavior a+concatSegment :: Monoid a => Event (Segment a) -> Behavior a concatSegment = trim . view bounded  -- |@@ -345,8 +337,8 @@ -- See also 'concatB' and 'continous'. -- concatS :: Monoid a => Score (Segment a) -> Behavior a-concatS = mconcat . map concatSegment . view notes--- Or: mconcat.fmap trim.toListOf (notes.each.bounded)+concatS = mconcat . map concatSegment . view events+-- Or: mconcat.fmap trim.toListOf (events.each.bounded)  -- | -- Concatenate a score of (possibly overlapping) segments.@@ -355,7 +347,7 @@ -- concatB :: Monoid a => Score (Behavior a) -> Behavior a concatB = concatS . fmap (view focusing)--- Or (more generally): mconcat.toListOf (notes.each.noteValue)+-- Or (more generally): mconcat.toListOf (events.each.eventee)   -- |@@ -368,8 +360,6 @@ focusing :: Lens' (Behavior a) (Segment a) focusing = lens get set   where-    get = view (from bounded . noteValue) . {-pure-}bounding mempty+    get = view (from bounded . eventee) . {-pure-}bounding mempty     set x = splice x . (view bounded) . pure---- JUNK 
src/Music/Time/Split.hs view
@@ -1,20 +1,14 @@  {-# LANGUAGE ConstraintKinds            #-} {-# LANGUAGE DeriveDataTypeable         #-}-{-# LANGUAGE DeriveFoldable             #-} {-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE DeriveFoldable             #-} {-# LANGUAGE DeriveTraversable          #-}-{-# LANGUAGE FlexibleContexts           #-}-{-# LANGUAGE FlexibleInstances          #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses      #-}-{-# LANGUAGE NoMonomorphismRestriction  #-}-{-# LANGUAGE RankNTypes                 #-}-{-# LANGUAGE ScopedTypeVariables        #-} {-# LANGUAGE StandaloneDeriving         #-} {-# LANGUAGE TupleSections              #-} {-# LANGUAGE TypeFamilies               #-}-{-# LANGUAGE UndecidableInstances       #-} {-# LANGUAGE ViewPatterns               #-}  -------------------------------------------------------------------------------------
− src/Music/Time/Stretched.hs
@@ -1,156 +0,0 @@--{-# LANGUAGE ConstraintKinds            #-}-{-# LANGUAGE DeriveDataTypeable         #-}-{-# LANGUAGE DeriveFoldable             #-}-{-# LANGUAGE DeriveFunctor              #-}-{-# LANGUAGE DeriveTraversable          #-}-{-# LANGUAGE FlexibleContexts           #-}-{-# LANGUAGE FlexibleInstances          #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MultiParamTypeClasses      #-}-{-# LANGUAGE NoMonomorphismRestriction  #-}-{-# LANGUAGE RankNTypes                 #-}-{-# LANGUAGE ScopedTypeVariables        #-}-{-# LANGUAGE StandaloneDeriving         #-}-{-# LANGUAGE TupleSections              #-}-{-# LANGUAGE TypeFamilies               #-}-{-# LANGUAGE UndecidableInstances       #-}------------------------------------------------------------------------------------------ |--- Copyright   : (c) Hans Hoglund 2012-2014------ License     : BSD-style------ Maintainer  : hans@hanshoglund.se--- Stability   : experimental--- Portability : non-portable (TF,GNTD)-------------------------------------------------------------------------------------------module Music.Time.Stretched (-        -- * Stretched type-        Stretched,--        -- * Construction-        stretched,-        stretchedValue,   -  ) where--import           Data.AffineSpace-import           Data.AffineSpace.Point-import           Data.Bifunctor-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.VectorSpace-import           Data.String-import           Data.Functor.Couple--import           Control.Applicative-import           Control.Comonad-import           Control.Comonad.Env-import           Control.Lens           hiding (Indexable, Level, above, below,-                                         index, inside, parts, reversed,-                                         transform, (<|), (|>))-import           Data.Foldable          (Foldable)-import qualified Data.Foldable          as Foldable-import           Data.PairMonad-import           Data.Typeable--import           Music.Dynamics.Literal-import           Music.Pitch.Literal-import           Music.Time.Reverse-import           Music.Time.Split----- |--- A 'Stretched' value has a known 'duration', but no 'position'.------ Placing a value inside 'Stretched' makes it invariant under 'delay', however the inner--- value can still be delayed using @'fmap' 'delay'@.----newtype Stretched a = Stretched { _stretchedValue :: Couple Duration a }-  deriving (Applicative, Monad, {-Comonad, -}-            Functor,  Foldable, Traversable)---- $semantics Stretched------ @--- type Stretched = (Duration, a)--- @------- >>> stretch 2 $ (5,1)^.stretched--- (10,1)^.stretched------ >>> delay 2 $ (5,1)^.stretched--- (5,1)^.stretched-----deriving instance Eq  a => Eq  (Stretched a)-deriving instance Num a => Num (Stretched a)-deriving instance Fractional a => Fractional (Stretched a)-deriving instance Floating a => Floating (Stretched a)-deriving instance Ord a => Ord (Stretched a)-deriving instance Real a => Real (Stretched a)-deriving instance RealFrac a => RealFrac (Stretched a)--deriving instance Typeable1 Stretched--instance Wrapped (Stretched a) where-  type Unwrapped (Stretched a) = (Duration, a)-  _Wrapped' = iso (getCouple . _stretchedValue) (Stretched . Couple)--instance Rewrapped (Stretched a) (Stretched b)--instance Transformable (Stretched a) where-  transform t = over _Wrapped $ first (transform t)--instance HasDuration (Stretched a) where-  _duration = _duration . ask . view _Wrapped--instance Reversible (Stretched a) where-  rev = stretch (-1)--instance Splittable a => Splittable (Stretched a) where-  beginning d = over _Wrapped $ \(s, v) -> (beginning d s, beginning d v)-  ending    d = over _Wrapped $ \(s, v) -> (ending    d s, ending    d v)--instance (Show a, Transformable a) => Show (Stretched a) where-  show x = show (x^.from stretched) ++ "^.stretched"---- Lifted instances--instance IsString a => IsString (Stretched a) where-  fromString = pure . fromString--instance IsPitch a => IsPitch (Stretched a) where-  fromPitch = pure . fromPitch--instance IsInterval a => IsInterval (Stretched a) where-  fromInterval = pure . fromInterval--instance IsDynamics a => IsDynamics (Stretched a) where-  fromDynamics = pure . fromDynamics---- |--- View a stretched value as a pair of the original value and a stretch factor.----stretched :: Iso (Duration, a) (Duration, b) (Stretched a) (Stretched b)-stretched = _Unwrapped----- |--- View a stretched value as a pair of the original value and the transformation (and vice versa).----stretchedValue :: (Transformable a, Transformable b) => Lens (Stretched a) (Stretched b) a b-stretchedValue = lens runStretched (flip $ _stretched . const)-  where-    _stretched f (Stretched (Couple (d, x))) = Stretched (Couple (d, f `whilst` stretching d $ x))-    runStretched = uncurry stretch . view _Wrapped-{-# INLINE stretchedValue #-}-
src/Music/Time/Track.hs view
@@ -1,20 +1,15 @@  {-# LANGUAGE ConstraintKinds            #-} {-# LANGUAGE DeriveDataTypeable         #-}-{-# LANGUAGE DeriveFoldable             #-} {-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE DeriveFoldable             #-} {-# LANGUAGE DeriveTraversable          #-}-{-# LANGUAGE FlexibleContexts           #-}-{-# LANGUAGE FlexibleInstances          #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses      #-}-{-# LANGUAGE NoMonomorphismRestriction  #-}-{-# LANGUAGE RankNTypes                 #-}-{-# LANGUAGE ScopedTypeVariables        #-} {-# LANGUAGE StandaloneDeriving         #-} {-# LANGUAGE TupleSections              #-} {-# LANGUAGE TypeFamilies               #-}-{-# LANGUAGE UndecidableInstances       #-}+{-# LANGUAGE ViewPatterns               #-}  ------------------------------------------------------------------------------------- -- |@@ -36,8 +31,7 @@          -- * Construction         track,-        delayeds,-        singleDelayed,   +        placeds,    ) where @@ -52,7 +46,7 @@ import qualified Data.Set               as Set import           Data.VectorSpace -import           Music.Time.Delayed+import           Music.Time.Placed import           Music.Time.Reverse import           Music.Time.Split @@ -72,14 +66,15 @@  -- | -- A 'Track' is a parallel composition of values.+newtype Track a = Track { getTrack :: TrackList (TrackEv a) }+  deriving (Functor, Foldable, Traversable, Semigroup, Monoid, Typeable, Show, Eq)+-- {-# DEPRECATED Track "Use 'Chord'" #-}+ -- -- @--- type Track a = [Delayed a]+-- type Track a = [Placed a] -- @ ---newtype Track a = Track { getTrack :: TrackList (TrackEv a) }-  deriving (Functor, Foldable, Traversable, Semigroup, Monoid, Typeable, Show, Eq)--- {-# DEPRECATED Track "Use 'Chord'" #-}  -- A track is a list of events with explicit onset. --@@ -96,9 +91,9 @@ type TrackList = []  -- Can use any type as long as trackEv provides an Iso-type TrackEv a = Delayed a+type TrackEv a = Placed a -trackEv :: Iso (Delayed a) (Delayed b) (TrackEv a) (TrackEv b)+trackEv :: Iso (Placed a) (Placed b) (TrackEv a) (TrackEv b) trackEv = id  instance Applicative Track where@@ -119,45 +114,26 @@  instance Rewrapped (Track a) (Track b) -instance Transformable (Track a) where+instance Transformable a => Transformable (Track a) where   transform s = over _Wrapped' (transform s) -instance HasPosition (Track a) where-  _onset  = safeMinimum . fmap _onset . view _Wrapped'-  _offset = safeMaximum . fmap _offset . view _Wrapped'---- TODO move-safeMinimum xs = if null xs then 0 else minimum xs-safeMaximum xs = if null xs then 0 else maximum xs--instance HasDuration (Track a) where-  _duration x = _offset x .-. _onset x--instance Splittable a => Splittable (Track a) where-  -- TODO+-- instance Splittable a => Splittable (Track a) where+--   -- TODO -instance Reversible a => Reversible (Track a) where-  -- TODO+-- instance Reversible a => Reversible (Track a) where+--   -- TODO  --- |--- Create a track from a list of notes.------ Se also 'delayeds'.----track :: Getter [Delayed a] (Track a)+-- | Create a track from a list of notes.+track :: Getter [Placed a] (Track a) track = from unsafeTrack {-# INLINE track #-} -delayeds :: Lens (Track a) (Track b) [Delayed a] [Delayed b]-delayeds = unsafeTrack-{-# INLINE delayeds #-}--singleDelayed :: Prism' (Track a) (Delayed a)-singleDelayed = unsafeTrack . single-{-# INLINE singleDelayed #-}+placeds :: Lens (Track a) (Track b) [Placed a] [Placed b]+placeds = unsafeTrack+{-# INLINE placeds #-} -unsafeTrack :: Iso (Track a) (Track b) [Delayed a] [Delayed b]+unsafeTrack :: Iso (Track a) (Track b) [Placed a] [Placed b] unsafeTrack = _Wrapped {-# INLINE unsafeTrack #-} 
src/Music/Time/Transform.hs view
@@ -34,12 +34,7 @@          -- * The Transformable class         Transformable(..),-        itransform,         transformed,-        whilst,-        spanned,-        onSpan,-        conjugateS,          -- * Specific transformations         -- ** Transformations@@ -53,7 +48,6 @@         undelay,         stretch,         compress,-        delayTime,    ) where 
src/Music/Time/Types.hs view
@@ -33,62 +33,59 @@ module Music.Time.Types (          -- * Basic types-        -- ** Time points         Time,-        toTime,-        fromTime,--        -- ** Duration         Duration,-        toDuration,-        fromDuration,+        LocalDuration,          -- ** Convert between time and duration         -- $convert         offsetPoints,+        pointOffsets,         toAbsoluteTime,         toRelativeTime,         toRelativeTimeN,-        toRelativeTimeN',+        toRelativeTimeN', -- TODO Fairbairn threshold          -- * Time spans         Span,-        -- *** Creating spans++        -- ** Constructing spans         (<->),         (>->),         (<-<),-        -- *** Accessing spans-        range,+         delta,+        range,         codelta, -        -- ** Properties-        -- $forwardBackWardEmpty-        isForwardSpan,-        isBackwardSpan,-        isEmptySpan,+        stretchComponent,+        delayComponent,+        fixedDurationSpan,+        fixedOnsetSpan,          -- ** Transformations+        normalizeSpan,         reverseSpan,         reflectSpan,-        normalizeSpan,         -        -- ** Delay and stretch component-        delayComponent,-        stretchComponent,-        fixedOnsetSpan,-        fixedDurationSpan,+        -- ** Properties+        isEmptySpan,+        isForwardSpan,+        isBackwardSpan,         +        -- delayComponent,+        -- stretchComponent,+         -- ** Points in spans         inside,          -- ** Partial orders-        isProper,-        isBefore,         encloses,         properlyEncloses,         overlaps,-        ++        -- *** etc.+        isBefore,         afterOnset,         strictlyAfterOnset,         beforeOnset,@@ -122,13 +119,10 @@ import           Control.Lens           hiding (Indexable, Level, above, below,                                          index, inside, parts, reversed,                                          transform, (<|), (|>))--- import           Control.Applicative.Backwards import           Control.Monad.State.Lazy--- import           Data.Aeson (ToJSON(..)) import qualified Data.Aeson as JSON- import           Data.AffineSpace import           Data.AffineSpace.Point import           Data.Semigroup@@ -136,7 +130,6 @@ import           Data.VectorSpace import           Data.List (mapAccumL, mapAccumR) import           Data.Ratio- import           Music.Time.Internal.Util (showRatio) -- import           Data.Fixed @@ -152,7 +145,7 @@ -- for 'Fractional' and 'RealFrac'. -- type TimeBase = Rational--- type TimeBase = Fixed E12+ {- type TimeBase = Fixed E12 @@ -161,39 +154,50 @@   negateV = negate   (^+^) = (+) --- Can be enabled for experimental time representation instance Floating TimeBase where deriving instance Floating Time deriving instance Floating Duration -} +type LocalDuration = Duration + -- | -- Duration, corresponding to note values in standard notation. -- The standard names can be used: @1\/2@ for half note @1\/4@ for a quarter note and so on. --+newtype Duration = Duration { getDuration :: TimeBase }+  deriving (+    Eq,+    Ord,+    Typeable,+    Enum,+    +    Num,+    Fractional,+    Real,+    RealFrac+    )+ -- Duration is a one-dimensional 'VectorSpace', and is the associated vector space of time points. -- It is a also an 'AdditiveGroup' (and hence also 'Monoid' and 'Semigroup') under addition. -- -- 'Duration' is invariant under translation so 'delay' has no effect on it. ---newtype Duration = Duration { getDuration :: TimeBase }-  deriving (Eq, Ord, Num, Enum, Fractional, Real, RealFrac, Typeable) --- $semantics Duration------ type Duration = R---- instance Show Duration where-  show = showRatio . realToFrac+  show = showRatio . toRational  instance ToJSON Duration where   toJSON = JSON.Number . realToFrac -instance InnerSpace Duration where-  (<.>) = (*)+instance Semigroup Duration where+  (<>) = (*^) +instance Monoid Duration where+  mempty  = 1+  mappend = (*^)+ instance AdditiveGroup Duration where   zeroV = 0   (^+^) = (+)@@ -203,177 +207,136 @@   type Scalar Duration = Duration   (*^) = (*) -instance Semigroup Duration where-  (<>) = (*^)+instance InnerSpace Duration where+  (<.>) = (*) -instance Monoid Duration where-  mempty  = 1-  mappend = (*^)- -- TODO use some notion of norm rather than 1 --- |--- Convert a value to a duration.+-- | 'Time' represents points in time space. The difference between two time points+-- is a 'Duration', for example in a bar of duration 4/4 (that is 1), the difference+-- between the first and third beat 1/2. ---toDuration :: Real a => a -> Duration-toDuration = realToFrac---- |--- Convert a value to a duration.+-- Time has an origin (zero) which usually represents the beginning of the musical+-- performance, but this may not always be the case, as the modelled music may be+-- infinite, or contain a musical pickup. Hence 'Time' values can be negative. ---fromDuration :: Fractional a => Duration -> a-fromDuration = realToFrac+newtype Time = Time { getTime :: TimeBase }+  deriving (+    Eq,+    Ord,+    Typeable,+    Enum, +    Num,+    Fractional,+    Real,+    RealFrac+    ) --- |--- Time points, representing duration since some known reference time, typically the start--- of the music. Note that time can be negative, representing values occuring before the--- reference time.--- -- Time forms an affine space with durations as the underlying vector space, that is, we -- can add a time to a duration to get a new time using '.+^', take the difference of two -- times to get a duration using '.-.'. 'Time' forms an 'AffineSpace' with 'Duration' as -- difference space.----newtype Time = Time { getTime :: TimeBase }-  deriving (Eq, Ord, Num, Enum, Fractional, Real, RealFrac, Typeable) --- $semantics Time------ type Time = R---- instance Show Time where-  show = showRatio . realToFrac+  show = showRatio . toRational  instance ToJSON Time where   toJSON = JSON.Number . realToFrac -deriving instance AdditiveGroup Time--instance VectorSpace Time where-  type Scalar Time = Duration-  Duration x *^ Time y = Time (x * y)--instance AffineSpace Time where-  type Diff Time = Duration-  Time x .-. Time y   = Duration (x - y)-  Time x .+^ Duration y = Time   (x + y)- instance Semigroup Time where-  (<>) = (^+^)+  (<>)    = (+)  instance Monoid Time where-  mempty  = zeroV-  mappend = (^+^)-  mconcat = sumV+  mempty  = 0+  mappend = (+) --- |--- Convert a value to a duration.----toTime :: Real a => a -> Time-toTime = realToFrac+instance AdditiveGroup Time where+  zeroV   = 0+  (^+^)   = (+)+  negateV = negate --- |--- Convert a value to a duration.----fromTime :: Fractional a => Time -> a-fromTime = realToFrac+instance VectorSpace Time where+  type Scalar Time = LocalDuration+  Duration x *^ Time y = Time (x * y) +instance AffineSpace Time where+  type Diff Time = LocalDuration+  Time x .-. Time y     = Duration (x - y)+  Time x .+^ Duration y = Time     (x + y) +-- | Lay out a series of vectors from a given point. Return all intermediate points.+-- +-- > lenght xs + 1 == length (offsetPoints p xs)+-- +-- >>> offsetPoints 0 [1,1,1] :: [Time]+-- [0,1,2,3]+offsetPoints :: AffineSpace p => p -> [Diff p] -> [p]+offsetPoints = scanl (.+^) --- TODO terminology--- Return the "accumulative sum" of the given vecors+-- | Calculate the relative difference between vectors.+-- +-- > lenght xs + 1 == length (offsetPoints p xs)+-- +-- >>> offsetPoints 0 [1,1,1] :: [Time]+-- [0,1,2,3]+pointOffsets :: AffineSpace p => p -> [p] -> [Diff p]+pointOffsets or = (zeroV :) . snd . mapAccumL g or+  where+    g prev p = (p, p .-. prev) --- |--- @length (offsetPoints x xs) = length xs + 1@+-- | Interpret as durations from 0. ----- >>> offsetPoints (0 ::Double) [1,2,1]--- [0.0,1.0,3.0,4.0]+-- > toAbsoluteTime (toRelativeTime xs) == xs ----- @--- offsetPoints :: 'AffineSpace' a => 'Time' -> ['Duration'] -> ['Time']--- @+-- > lenght xs == length (toRelativeTime xs) ---offsetPoints :: AffineSpace a => a -> [Diff a] -> [a]-offsetPoints = scanl (.+^)---- | Convert to delta (time to wait before this note)-toRelativeTime :: [Time] -> [Duration]-toRelativeTime = snd . mapAccumL g 0 where g prev t = (t, t .-. prev)--- toRelativeTime xs = fst $ mapAccumL2 g xs 0 where g t prev = (t .-. prev, t)---- | Convert to delta (time to wait before next note)-toRelativeTimeN :: [Time] -> [Duration]-toRelativeTimeN [] = []-toRelativeTimeN xs = toRelativeTimeN' (last xs) xs---- | Convert to delta (time to wait before next note)-toRelativeTimeN' :: Time -> [Time] -> [Duration]-toRelativeTimeN' end xs = snd $ mapAccumR g end xs where g prev t = (t, prev .-. t)--{--TODO consolidate with this beat (used in Midi export)--toRelative = snd . List.mapAccumL g 0-    where-        g now (t,d,x) = (t, (0 .+^ (t .-. now),d,x))---}--- 0 x,1 x,1 x,1 x-  -- x 1,x 1,x 1,x 0---- | Convert from delta (time to wait before this note)+-- >>> toAbsoluteTime [1,1,1] :: [Time]+-- [1,2,3] toAbsoluteTime :: [Duration] -> [Time] toAbsoluteTime = tail . offsetPoints 0 ------ TODO use State instead---- mapAccumL                 ::                   (s -> a -> (s, b)) -> s -> [a] -> (s, [b])--- \f -> mapM (runState . f) :: MonadState s m => (a -> s -> (b, s)) -> [a] -> s -> ([b], s)---- mapAccumL :: (s -> a -> (s, b)) -> s -> [a] -> (s, [b])-mapAccumL2   :: (a -> s -> (b, s)) -> [a] -> s -> ([b], s)-mapAccumL2 f = runState . mapM (state . f)-+-- | Duration between 0 and first value and so on until the last.+-- +-- > toAbsoluteTime (toRelativeTime xs) == xs+-- +-- > lenght xs == length (toRelativeTime xs)+-- +-- >>> toRelativeTime [1,2,3]+-- [1,1,1]+toRelativeTime :: [Time] -> [Duration]+toRelativeTime = tail . pointOffsets 0 +-- TODO rename these two... +-- | Duration between values until the last, then up to the given final value.+-- > lenght xs == length (toRelativeTime xs)+toRelativeTimeN' :: Time -> [Time] -> [Duration]+toRelativeTimeN' or = snd . Data.List.mapAccumR g or+  where+    g prev p = (p, prev .-. p) +-- Same as toRelativeTimeN' but always returns 0 as the last value...+-- TODO remove+toRelativeTimeN :: [Time] -> [Duration]+toRelativeTimeN [] = []+toRelativeTimeN xs = toRelativeTimeN' (last xs) xs    -- |--- A 'Span' represents an onset and offset in time (or equivalently: an onset and a--- duration, /or/ a duration and an offset, /or/ a duration and a middle point).------ Pattern matching over span is possible (with @ViewPatterns@):------ @--- foo ('view' 'range'   -> (t1, t2)) = ...--- foo ('view' 'delta'   -> (t1, d))  = ...--- foo ('view' 'codelta' -> (d,  t2)) = ...--- @+-- A 'Span' represents a specific time interval, such as the duration of+-- a note, phrase or musical piece. It can be modelled as two points, or as+-- a point and a vector. -- -- Another way of looking at 'Span' is that it represents a time transformation where -- onset is translation and duration is scaling. ----- TODO How to use with 'transform', 'whilst' etc.------ @--- a '<->' b = (a, b)^.'from' 'range'--- a '>->' b = (a, b)^.'from' 'delta'--- a '<-<' b = (a, b)^.'from' 'codelta'--- @----newtype Span = Delta { _delta :: (Time, Duration) }-  deriving (Eq, Ord, Typeable)---- $semantics------ type Span = Time x Time---+newtype Span = Span { getSpan :: (Time, Duration) }+  deriving (+    Eq,+    Ord,+    Typeable+    )  -- You can create a span using the constructors '<->', '<-<' and '>->'. Note that: --@@ -407,37 +370,28 @@ --  instance Show Span where-  -- show = showDelta   show = showRange   -- Which form should we use?  instance ToJSON Span where   toJSON (view range -> (a,b)) = JSON.object [ ("onset", toJSON a), ("offset", toJSON b) ] ---- |--- 'zeroV' or 'mempty' represents the /unit interval/ @0 \<-\> 1@, which also happens to--- be the identity transformation.--- instance Semigroup Span where   (<>) = (^+^) --- |--- '<>' or '^+^' composes transformations, i.e. both time and duration is stretched,--- and then time is added.--- instance Monoid Span where   mempty  = zeroV   mappend = (^+^) --- |--- 'negateV' returns the inverse of a given transformation.--- instance AdditiveGroup Span where-  zeroV   = 0 <-> 1-  Delta (t1, d1) ^+^ Delta (t2, d2) = Delta (t1 ^+^ d1 *^ t2, d1*d2)-  negateV (Delta (t, d)) = Delta (-t ^/ d, recip d)+  zeroV                           = 0 <-> 1+  Span (t1, d1) ^+^ Span (t2, d2) = Span (t1 ^+^ d1 *^ t2, d1*d2)+  negateV (Span (t, d))           = Span (-t ^/ d, recip d) +instance VectorSpace Span where+  type Scalar Span = Duration+  x *^ Span (t, d) = Span (x*^t, x*^d)+ -- -- a >-> b = a         <-> (a .+^ b) -- a <-< b = (b .-^ a) <-> b@@ -459,7 +413,7 @@ -- @t >-> d@ represents the span between @t@ and @t .+^ d@. -- (>->) :: Time -> Duration -> Span-(>->) = curry Delta+(>->) = curry Span  -- | -- @d \<-\> t@ represents the span between @t .-^ d@ and @t@.@@ -472,23 +426,20 @@ -- View a span as pair of onset and offset. -- range :: Iso' Span (Time, Time)-range = iso _range $ uncurry (<->)-  where-    _range x = let (t, d) = _delta x in (t, t .+^ d)+range = iso (\x -> let (t, d) = getSpan x in (t, t .+^ d)) (uncurry (<->))  -- | -- View a span as a pair of onset and duration. --+ delta :: Iso' Span (Time, Duration)-delta = iso _delta Delta+delta = iso getSpan Span  -- | -- View a span as a pair of duration and offset. -- codelta :: Iso' Span (Duration, Time)-codelta = iso _codelta $ uncurry (<-<)-  where-    _codelta x = let (t, d) = _delta x in (d, t .+^ d)+codelta = iso (\x -> let (t, d) = getSpan x in (d, t .+^ d)) (uncurry (<-<))  -- | -- Show a span in range notation, i.e. @t1 \<-\> t2@.@@ -786,8 +737,5 @@   a + b     = a + b -} --- TODO move-fraction :: (RealFrac a, Integral b) => Iso' a (b, b) -fraction = iso (\(toRational -> a) -> (fromIntegral $ numerator a, fromIntegral $ denominator a)) (\(a,b) -> fromIntegral a / fromIntegral b)  
src/Music/Time/Voice.hs view
@@ -1,20 +1,15 @@  {-# LANGUAGE ConstraintKinds            #-} {-# LANGUAGE DeriveDataTypeable         #-}-{-# LANGUAGE DeriveFoldable             #-} {-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE DeriveFoldable             #-} {-# LANGUAGE DeriveTraversable          #-}-{-# LANGUAGE FlexibleContexts           #-}-{-# LANGUAGE FlexibleInstances          #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses      #-}-{-# LANGUAGE NoMonomorphismRestriction  #-} {-# LANGUAGE RankNTypes                 #-}-{-# LANGUAGE ScopedTypeVariables        #-} {-# LANGUAGE StandaloneDeriving         #-} {-# LANGUAGE TupleSections              #-} {-# LANGUAGE TypeFamilies               #-}-{-# LANGUAGE UndecidableInstances       #-} {-# LANGUAGE ViewPatterns               #-}  -------------------------------------------------------------------------------------@@ -36,30 +31,20 @@          -- * Construction         voice,--        -- ** Extracting values-        stretcheds,-        eventsV,-        singleStretched,--        -- * Fusion-        fuse,-        fuseBy,--        -- ** Fuse rests-        fuseRests,-        coverRests,+        notes,+        pairs,+        durationsVoice,          -- * Traversal         -- ** Separating rhythms and values         valuesV,         durationsV,-        withValues,-        withDurations,-        rotateValues,-        rotateDurations,-        reverseValues,-        reverseDurations,+        -- withValues,+        -- withDurations,+        -- rotateValues,+        -- rotateDurations,+        -- reverseValues,+        -- reverseDurations,          -- ** Zips         unzipVoice,@@ -74,16 +59,34 @@         zipVoiceWith',         zipVoiceWithNoScale, +        -- * Fusion+        fuse,+        fuseBy,++        -- ** Fuse rests+        fuseRests,+        coverRests,+        +        -- * Homophonic/Polyphonic texture+        sameDurations,+        mergeIfSameDuration,+        mergeIfSameDurationWith,+        homoToPolyphonic,++        -- * Points in a voice+        onsetsRelative,+        offsetsRelative,+        midpointsRelative,+        erasRelative,+                 -- * Context+        -- TODO clean         withContext,-        voiceLens,-        -- voiceL,-        voiceAsList,-        listAsVoice,+        -- voiceLens,          -- * Unsafe versions-        unsafeStretcheds,-        unsafeEventsV,+        unsafeNotes,+        unsafePairs,    ) where @@ -105,7 +108,7 @@  import           Music.Time.Reverse import           Music.Time.Split-import           Music.Time.Stretched+import           Music.Time.Note  import           Control.Applicative import           Control.Lens             hiding (Indexable, Level, above,@@ -126,23 +129,37 @@ import           Music.Time.Internal.Util  -- |--- A 'Voice' is a sequential composition of values. Events may not overlap.+-- A 'Voice' is a sequential composition of non-overlapping note values. ---newtype Voice a = Voice { getVoice :: VoiceList (VoiceEv a) }-  deriving (Functor, Foldable, Traversable, Semigroup, Monoid, Typeable, Eq)--instance (Show a, Transformable a) => Show (Voice a) where-  show x = show (x^.stretcheds) ++ "^.voice"-+-- Both 'Voice' and 'Note' have duration but no position. The difference+-- is that 'Note' sustains a single value throughout its duration, while+-- a voice may contain multiple values. It is called voice because it is+-- generalizes the notation of a voice in choral or multi-part instrumental music. ----- $semantics Voice--- type Voice a = [Stretched a]+-- It may be useful to think about 'Voice' and 'Note' as vectors in time space+-- (i.e. 'Duration'), that also happens to carry around other values, such as pitches. --+newtype Voice a = Voice { getVoice :: [Note a] }+  deriving (+    Eq,+    Ord,+    Typeable,+    Foldable, +    Traversable,  +    Functor, +    Semigroup, +    Monoid +    )++instance (Show a, Transformable a) => Show (Voice a) where+  show x = show (x^.notes) ++ "^.voice"+ -- A voice is a list of events with explicit duration. Events can not overlap. -- -- Voice is a 'Monoid' under sequential composition. 'mempty' is the empty part and 'mappend' -- appends parts.+ -- -- Voice is a 'Monad'. 'return' creates a part containing a single value of duration -- one, and '>>=' transforms the values of a part, allowing the addition and@@ -150,20 +167,6 @@ -- each inner part to the duration of the outer part, then removes the -- intermediate structure. --- Can use [] or Seq here-type VoiceList = []---- Can use any type as long as voiceEv provides an Iso-type VoiceEv a = Stretched a--- type VoiceEv a = ((),Stretched a)--voiceEv :: Iso (Stretched a) (Stretched b) (VoiceEv a) (VoiceEv b)-voiceEv = id--- voiceEv = iso add remove---   where---     add x = ((),x)---     remove ((),x) = x- instance Applicative Voice where   pure  = return   (<*>) = ap@@ -181,40 +184,37 @@   mplus = mappend    instance Wrapped (Voice a) where-  type Unwrapped (Voice a) = (VoiceList (VoiceEv a))+  type Unwrapped (Voice a) = [Note a]   _Wrapped' = iso getVoice Voice  instance Rewrapped (Voice a) (Voice b) -instance Cons (Voice a) (Voice b) (Stretched a) (Stretched b) where-  _Cons = prism (\(s,v) -> (view voice.return $ s) <> v) $ \v -> case view stretcheds v of+instance Cons (Voice a) (Voice b) (Note a) (Note b) where+  _Cons = prism (\(s,v) -> (view voice.return $ s) <> v) $ \v -> case view notes v of     []      -> Left  mempty     (x:xs)  -> Right (x, view voice xs) -instance Snoc (Voice a) (Voice b) (Stretched a) (Stretched b) where-  _Snoc = prism (\(v,s) -> v <> (view voice.return $ s)) $ \v -> case unsnoc (view stretcheds v) of+instance Snoc (Voice a) (Voice b) (Note a) (Note b) where+  _Snoc = prism (\(v,s) -> v <> (view voice.return $ s)) $ \v -> case unsnoc (view notes v) of     Nothing      -> Left  mempty     Just (xs, x) -> Right (view voice xs, x)  instance Transformable (Voice a) where-  transform s = over _Wrapped' (transform s)+  transform s = over notes (transform s)  instance HasDuration (Voice a) where-  _duration = Foldable.sum . fmap _duration . view _Wrapped'--instance Splittable a => Splittable (Voice a) where-  split t x-    | t <= 0           = (mempty, x)-    | t >= _duration x = (x,      mempty)-    | otherwise        = let (a,b) = split' t {-split-} (x^._Wrapped) in (a^._Unwrapped, b^._Unwrapped)-    where-      split' = error "TODO"+  _duration = sumOf (notes . each . duration)  instance Reversible a => Reversible (Voice a) where-  rev = over _Wrapped' (fmap rev) -- TODO OK?-+  rev = over notes reverse . fmap rev --- Lifted instances+-- instance Splittable a => Splittable (Voice a) where+--   split t x+--     | t <= 0           = (mempty, x)+--     | t >= _duration x = (x,      mempty)+--     | otherwise        = let (a,b) = split' t {-split-} (x^._Wrapped) in (a^._Unwrapped, b^._Unwrapped)+--     where+--       split' = error "TODO"  instance IsString a => IsString (Voice a) where   fromString = pure . fromString@@ -238,101 +238,77 @@   fromInteger = return . fromInteger   abs    = fmap abs   signum = fmap signum-  (+)    = error "Not implemented"+  (+)    = (<>)   (-)    = error "Not implemented"   (*)    = error "Not implemented" --- Bogus instances, so we can use c^*2 etc. instance AdditiveGroup (Voice a) where-  zeroV   = error "Not implemented"-  (^+^)   = error "Not implemented"-  negateV = error "Not implemented"+  zeroV   = mempty+  (^+^)   = (<>)+  negateV = error "Not implemented" -- TODO negate durations  instance VectorSpace (Voice a) where   type Scalar (Voice a) = Duration   d *^ s = d `stretch` s  --- |--- Create a 'Voice' from a list of 'Stretched' values.------ This is a 'Getter' (rather than a function) for consistency:------ @--- [ (0 '<->' 1, 10)^.'stretched',---   (1 '<->' 2, 20)^.'stretched',---   (3 '<->' 4, 30)^.'stretched' ]^.'voice'--- @------ @--- 'view' 'voice' $ 'map' ('view' 'stretched') [(0 '<->' 1, 1)]--- @------ Se also 'stretcheds'.----voice :: Getter [Stretched a] (Voice a)-voice = from unsafeStretcheds--- voice = to $ flip (set stretcheds) empty+-- | Create a 'Voice' from a list of 'Note's.+voice :: Getter [Note a] (Voice a)+voice = from unsafeNotes {-# INLINE voice #-} --- |--- View a 'Voice' as a list of 'Stretched' values.+-- | View a 'Voice' as a list of 'Note' values.+notes :: Lens (Voice a) (Voice b) [Note a] [Note b]+notes = unsafeNotes+ -- -- @--- 'view' 'stretcheds'                        :: 'Voice' a -> ['Stretched' a]--- 'set'  'stretcheds'                        :: ['Stretched' a] -> 'Voice' a -> 'Voice' a--- 'over' 'stretcheds'                        :: (['Stretched' a] -> ['Stretched' b]) -> 'Voice' a -> 'Voice' b+-- 'view' 'notes'                        :: 'Voice' a -> ['Note' a]+-- 'set'  'notes'                        :: ['Note' a] -> 'Voice' a -> 'Voice' a+-- 'over' 'notes'                        :: (['Note' a] -> ['Note' b]) -> 'Voice' a -> 'Voice' b -- @ -- -- @--- 'preview'  ('stretcheds' . 'each')           :: 'Voice' a -> 'Maybe' ('Stretched' a)--- 'preview'  ('stretcheds' . 'element' 1)      :: 'Voice' a -> 'Maybe' ('Stretched' a)--- 'preview'  ('stretcheds' . 'elements' odd)   :: 'Voice' a -> 'Maybe' ('Stretched' a)+-- 'preview'  ('notes' . 'each')           :: 'Voice' a -> 'Maybe' ('Note' a)+-- 'preview'  ('notes' . 'element' 1)      :: 'Voice' a -> 'Maybe' ('Note' a)+-- 'preview'  ('notes' . 'elements' odd)   :: 'Voice' a -> 'Maybe' ('Note' a) -- @ -- -- @--- 'set'      ('stretcheds' . 'each')           :: 'Stretched' a -> 'Voice' a -> 'Voice' a--- 'set'      ('stretcheds' . 'element' 1)      :: 'Stretched' a -> 'Voice' a -> 'Voice' a--- 'set'      ('stretcheds' . 'elements' odd)   :: 'Stretched' a -> 'Voice' a -> 'Voice' a+-- 'set'      ('notes' . 'each')           :: 'Note' a -> 'Voice' a -> 'Voice' a+-- 'set'      ('notes' . 'element' 1)      :: 'Note' a -> 'Voice' a -> 'Voice' a+-- 'set'      ('notes' . 'elements' odd)   :: 'Note' a -> 'Voice' a -> 'Voice' a -- @ -- -- @--- 'over'     ('stretcheds' . 'each')           :: ('Stretched' a -> 'Stretched' b) -> 'Voice' a -> 'Voice' b--- 'over'     ('stretcheds' . 'element' 1)      :: ('Stretched' a -> 'Stretched' a) -> 'Voice' a -> 'Voice' a--- 'over'     ('stretcheds' . 'elements' odd)   :: ('Stretched' a -> 'Stretched' a) -> 'Voice' a -> 'Voice' a+-- 'over'     ('notes' . 'each')           :: ('Note' a -> 'Note' b) -> 'Voice' a -> 'Voice' b+-- 'over'     ('notes' . 'element' 1)      :: ('Note' a -> 'Note' a) -> 'Voice' a -> 'Voice' a+-- 'over'     ('notes' . 'elements' odd)   :: ('Note' a -> 'Note' a) -> 'Voice' a -> 'Voice' a -- @ -- -- @--- 'toListOf' ('stretcheds' . 'each')                :: 'Voice' a -> ['Stretched' a]--- 'toListOf' ('stretcheds' . 'elements' odd)        :: 'Voice' a -> ['Stretched' a]--- 'toListOf' ('stretcheds' . 'each' . 'filtered'---              (\\x -> '_duration' x \< 2))  :: 'Voice' a -> ['Stretched' a]+-- 'toListOf' ('notes' . 'each')                :: 'Voice' a -> ['Note' a]+-- 'toListOf' ('notes' . 'elements' odd)        :: 'Voice' a -> ['Note' a]+-- 'toListOf' ('notes' . 'each' . 'filtered'+--              (\\x -> '_duration' x \< 2))  :: 'Voice' a -> ['Note' a] -- @------ This is not an 'Iso', as the note list representation does not contain meta-data.--- To construct a score from a note list, use 'score' or @'flip' ('set' 'stretcheds') 'empty'@.----stretcheds :: Lens (Voice a) (Voice b) [Stretched a] [Stretched b]-stretcheds = unsafeStretcheds-{-# INLINE stretcheds #-} -eventsV :: Lens (Voice a) (Voice b) [(Duration, a)] [(Duration, b)]-eventsV = unsafeEventsV-{-# INLINE eventsV #-}--unsafeEventsV :: Iso (Voice a) (Voice b) [(Duration, a)] [(Duration, b)]-unsafeEventsV = iso (map (^.from stretched) . (^.stretcheds)) ((^.voice) . map (^.stretched))-{-# INLINE unsafeEventsV #-}+-- | View a score as a list of duration-value pairs. Analogous to 'triples'.+pairs :: Lens (Voice a) (Voice b) [(Duration, a)] [(Duration, b)]+pairs = unsafePairs -unsafeStretcheds :: Iso (Voice a) (Voice b) [Stretched a] [Stretched b]-unsafeStretcheds = _Wrapped-{-# INLINE unsafeStretcheds #-}+-- | A voice is a list of notes up to meta-data. To preserve meta-data, use the more+-- restricted 'voice' and 'notes'.+unsafeNotes :: Iso (Voice a) (Voice b) [Note a] [Note b]+unsafeNotes = _Wrapped -singleStretched :: Prism' (Voice a) (Stretched a)-singleStretched = unsafeStretcheds . single-{-# INLINE singleStretched #-}-{-# DEPRECATED singleStretched "Use 'unsafeStretcheds . single'" #-}+-- | A score is a list of (duration-value pairs) up to meta-data.+-- To preserve meta-data, use the more restricted 'pairs'.+unsafePairs :: Iso (Voice a) (Voice b) [(Duration, a)] [(Duration, b)]+unsafePairs = iso (map (^.from note) . (^.notes)) ((^.voice) . map (^.note)) +durationsVoice :: Iso' [Duration] (Voice ())+durationsVoice = iso (mconcat . fmap (\d -> stretch d $ pure ())) (^. durationsV)  -- | -- Unzip the given voice. This is specialization of 'unzipR'.@@ -406,12 +382,16 @@ -- zipVoiceWith' :: (Duration -> Duration -> Duration) -> (a -> b -> c) -> Voice a -> Voice b -> Voice c zipVoiceWith' f g-  ((unzip.view eventsV) -> (ad, as))-  ((unzip.view eventsV) -> (bd, bs))+  ((unzip.view pairs) -> (ad, as))+  ((unzip.view pairs) -> (bd, bs))   = let cd = zipWith f ad bd         cs = zipWith g as bs-     in view (from unsafeEventsV) (zip cd cs)+     in view (from unsafePairs) (zip cd cs) ++-- TODO generalize these to use a Monoidal interface, rather than ([a] -> a)+-- The use of head (see below) if of course the First monoid+ -- | -- Merge consecutive equal notes. --@@ -419,7 +399,7 @@ fuse = fuseBy (==)  -- |--- Merge consecutive equal notes using the given function.+-- Merge consecutive notes deemed equal by the given predicate. -- fuseBy :: (a -> a -> Bool) -> Voice a -> Voice a fuseBy p = fuseBy' p head@@ -428,7 +408,7 @@ -- Merge consecutive equal notes using the given equality predicate and merge function. -- fuseBy' :: (a -> a -> Bool) -> ([a] -> a) -> Voice a -> Voice a-fuseBy' p g = over unsafeEventsV $ fmap foldNotes . Data.List.groupBy (inspectingBy snd p)+fuseBy' p g = over unsafePairs $ fmap foldNotes . Data.List.groupBy (inspectingBy snd p)   where     -- Add up durations and use a custom function to combine notes     --@@ -447,7 +427,7 @@ -- if and only if the given voice contains rests only. -- coverRests :: Voice (Maybe a) -> Maybe (Voice a)-coverRests x = if hasOnlyRests then Nothing else Just (fmap fromJust $ fuseBy merge x)+coverRests x = if hasOnlyRests then Nothing else Just (fmap fromJust $ fuseBy merge x)   where     norm = fuseRests x     merge Nothing  Nothing  = error "Voice normalized, so consecutive rests are impossible"@@ -456,151 +436,66 @@     merge (Just x) (Just y) = False     hasOnlyRests = all isNothing $ toListOf traverse x -- norm -+-- | Decorate all notes in a voice with their context, i.e. previous and following value+-- if present. withContext :: Voice a -> Voice (Ctxt a)-withContext = over valuesV (fmap Ctxt . withPrevNext)---- TODO expose?-voiceFromRhythm :: [Duration] -> Voice ()-voiceFromRhythm = mkVoice . fmap (, ())--mkVoice = view voice . fmap (view stretched)+withContext = over valuesV addCtxt ------ TODO more elegant definition of durationsV and valuesV using indexed traversal or similar?---+-- TODO more elegant definition? +-- | A lens to the durations in a voice. durationsV :: Lens' (Voice a) [Duration] durationsV = lens getDurs (flip setDurs)   where     getDurs :: Voice a -> [Duration]-    getDurs = map fst . view eventsV+    getDurs = map fst . view pairs      setDurs :: [Duration] -> Voice a -> Voice a     setDurs ds as = zipVoiceWith' (\a b -> a) (\a b -> b) (mconcat $ map durToVoice ds) as      durToVoice d = stretch d $ pure () +-- | A lens to the values in a voice. valuesV :: Lens (Voice a) (Voice b) [a] [b] valuesV = lens getValues (flip setValues)   where-    getValues :: Voice a -> [a]-    getValues = map snd . view eventsV+    -- getValues :: Voice a -> [a]+    getValues = map snd . view pairs -    setValues :: [a] -> Voice b -> Voice a+    -- setValues :: [a] -> Voice b -> Voice a     setValues as bs = zipVoiceWith' (\a b -> b) (\a b -> a) (listToVoice as) bs      listToVoice = mconcat . map pure --- |--- Transform the durations, leaving values intact.-withDurations :: ([Duration] -> [Duration]) -> Voice a -> Voice a-withDurations = over durationsV---- |--- Transform the values, leaving durations intact.-withValues :: ([a] -> [b]) -> Voice a -> Voice b-withValues = over valuesV---- |--- Rotate durations by the given number of steps, leaving values intact.----rotateDurations :: Int -> Voice a -> Voice a-rotateDurations n = over durationsV (rotate n)---- |--- Rotate values by the given number of steps, leaving durations intact.----rotateValues :: Int -> Voice a -> Voice a-rotateValues n = over valuesV (rotate n)---- |--- Reverse durations, leaving values intact.----reverseDurations :: Voice a -> Voice a-reverseDurations = over durationsV reverse---- |--- Reverse values, leaving durations intact.----reverseValues :: Voice a -> Voice a-reverseValues = over valuesV reverse- -- Lens "filtered" through a voice voiceLens :: (s -> a) -> (b -> s -> t) -> Lens (Voice s) (Voice t) (Voice a) (Voice b) voiceLens getter setter = lens (fmap getter) (flip $ zipVoiceWithNoScale setter)---- TODO generalize to any zippable thing--- voiceL :: ALens s t a b -> Lens (Voice s) (Voice t) (Voice a) (Voice b)-voiceL l = voiceLens (view $ cloneLens l) (set $ cloneLens l)----- TODO not meta-safe-voiceAsList :: Iso (Voice a) (Voice b) [a] [b]-voiceAsList = iso voiceToList listToVoice-  where-    voiceToList = map snd . view eventsV-    listToVoice = mconcat . fmap pure--listAsVoice :: Iso [a] [b] (Voice a) (Voice b)-listAsVoice = from voiceAsList-------- TODO--- Implement meta-data------- List functions-headV, lastV :: Voice a -> Maybe (Stretched a)-headV = preview _head-lastV = preview _head--tailV, initV :: Voice a -> Maybe (Voice a)-tailV = preview _tail-initV = preview _init--consV :: Stretched a -> Voice a -> Voice a-unconsV :: Voice a -> Maybe (Stretched a, Voice a)-consV = cons-unconsV = uncons--snocV :: Voice a -> Stretched a -> Voice a-unsnocV :: Voice a -> Maybe (Voice a, Stretched a)-snocV = snoc-unsnocV = unsnoc--nullV :: Voice a -> Bool-nullV = nullOf eventsV--lengthV :: Voice a -> Int-lengthV = lengthOf eventsV--mapV :: (a -> b) -> Voice a -> Voice b-mapV = fmap----- Voice-specific+-- TODO could also use (zipVoiceWith' max) or (zipVoiceWith' min) +-- | Whether two notes have exactly the same duration pattern.+-- Two empty voices are considered to have the same duration pattern.+-- Voices with an non-equal number of notes differ by default. sameDurations :: Voice a -> Voice b -> Bool sameDurations a b = view durationsV a == view durationsV b +-- | Pair the values of two voices if and only if they have the same duration+-- pattern (as per 'sameDurations'). mergeIfSameDuration :: Voice a -> Voice b -> Maybe (Voice (a, b)) mergeIfSameDuration = mergeIfSameDurationWith (,) +-- | Combine the values of two voices using the given function if and only if they+-- have the same duration pattern (as per 'sameDurations'). mergeIfSameDurationWith :: (a -> b -> c) -> Voice a -> Voice b -> Maybe (Voice c) mergeIfSameDurationWith f a b   | sameDurations a b = Just $ zipVoiceWithNoScale f a b   | otherwise         = Nothing---- splitAt :: [Duration] -> Voice a -> [Voice a]--- splitTiesVoiceAt :: Tiable a => [Duration] -> Voice a -> [Voice a]+-- TODO could also use (zipVoiceWith' max) or (zipVoiceWith' min)  -- | -- Split all notes of the latter voice at the onset/offset of the former. ----- >>> ["a",(2,"b")^.stretched,"c"]^.voice--- [(1,"a")^.stretched,(2,"b")^.stretched,(1,"c")^.stretched]^.voice+-- >>> ["a",(2,"b")^.note,"c"]^.voice+-- [(1,"a")^.note,(2,"b")^.note,(1,"c")^.note]^.voice -- splitLatterToAssureSameDuration :: Voice b -> Voice b -> Voice b splitLatterToAssureSameDuration = splitLatterToAssureSameDurationWith dup@@ -616,8 +511,15 @@ polyToHomophonicForce :: [Voice a] -> Voice [a] polyToHomophonicForce = undefined +-- | Split a homophonic texture into a polyphonic one. The returned voice list will not+-- have as many elements as the chord with the fewest number of notes. homoToPolyphonic      :: Voice [a] -> [Voice a]-homoToPolyphonic = undefined+homoToPolyphonic xs = case nvoices xs of+  Nothing -> []+  Just n  -> fmap (\n -> fmap (!! n) xs) [0..n-1]+  where                  +    nvoices :: Voice [a] -> Maybe Int+    nvoices = maybeMinimum . fmap length . (^.valuesV)  changeCrossing   :: Ord a => Voice a -> Voice a -> (Voice a, Voice a) changeCrossing = undefined@@ -631,17 +533,25 @@ processExactOverlaps' :: (a -> b -> Either (a,b) (b,a)) -> Voice a -> Voice b -> (Voice (Either b a), Voice (Either a b)) processExactOverlaps' = undefined +-- | Returns the onsets of all notes in a voice given the onset of the first note. onsetsRelative    :: Time -> Voice a -> [Time]-onsetsRelative = undefined+onsetsRelative o v = case offsetsRelative o v of+  [] -> []+  xs -> o : init xs +-- | Returns the offsets of all notes in a voice given the onset of the first note. offsetsRelative   :: Time -> Voice a -> [Time]-offsetsRelative = undefined+offsetsRelative o = fmap (\t -> o .+^ (t .-. 0)) . toAbsoluteTime . (^. durationsV) +-- | Returns the midpoints of all notes in a voice given the onset of the first note. midpointsRelative :: Time -> Voice a -> [Time]-midpointsRelative = undefined+midpointsRelative o v = zipWith between (onsetsRelative o v) (offsetsRelative o v)+  where+    between p q = alerp p q 0.5 -erasRelative      :: Time -> Voice a -> [Span]-erasRelative = undefined+-- | Returns the eras of all notes in a voice given the onset of the first note.+erasRelative :: Time -> Voice a -> [Span]+erasRelative o v = zipWith (<->) (onsetsRelative o v) (offsetsRelative o v)  onsetMap  :: Time -> Voice a -> Map Time a onsetMap = undefined@@ -669,7 +579,7 @@ mergeIfSameDuration     :: Voice a -> Voice b -> Maybe (Voice (a, b)) mergeIfSameDurationWith :: (a -> b -> c) -> Voice a -> Voice b -> Maybe (Voice c) splitAt :: [Duration] -> Voice a -> [Voice a]--- splitTiesVoiceAt :: Tiable a => [Duration] -> Voice a -> [Voice a]+-- splitTiesAt :: Tiable a => [Duration] -> Voice a -> [Voice a] splitLatterToAssureSameDuration :: Voice b -> Voice b -> Voice b splitLatterToAssureSameDurationWith :: (b -> (b, b)) -> Voice b -> Voice b -> Voice b polyToHomophonic      :: [Voice a] -> Maybe (Voice [a])@@ -732,3 +642,5 @@  -} +maybeMinimum xs = if null xs then Nothing else Just (minimum xs)+maybeMaximum xs = if null xs then Nothing else Just (maximum xs)