packages feed

music-score 1.7.1 → 1.7.2

raw patch · 59 files changed

+2077/−1176 lines, 59 filesdep +averagedep ~adjunctionsdep ~bifunctorsdep ~comonadPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: average

Dependency ranges changed: adjunctions, bifunctors, comonad, contravariant, distributive, lens, lilypond, music-dynamics-literal, music-pitch-literal, musicxml2, profunctors

API changes (from Hackage documentation)

- Control.Lens.Cons.Middle: _middle :: (Snoc s s a a, Cons s s b b) => Traversal' s s
- Data.Average: Average :: [a] -> Average a
- Data.Average: average :: Fractional a => Average a -> a
- Data.Average: getAverage :: Average a -> [a]
- Data.Average: instance (Fractional a, Eq a) => Eq (Average a)
- Data.Average: instance (Fractional a, Num a) => Fractional (Average a)
- Data.Average: instance (Fractional a, Ord a) => Ord (Average a)
- Data.Average: instance (Real a, Fractional a) => Real (Average a)
- Data.Average: instance AdditiveGroup a => AdditiveGroup (Average a)
- Data.Average: instance AffineSpace a => AffineSpace (Average a)
- Data.Average: instance Applicative Average
- Data.Average: instance Floating a => Floating (Average a)
- Data.Average: instance Functor Average
- Data.Average: instance Monoid (Average a)
- Data.Average: instance Num a => Num (Average a)
- Data.Average: instance Semigroup (Average a)
- Data.Average: instance Show a => Show (Average a)
- Data.Average: instance Typeable1 Average
- Data.Average: instance VectorSpace a => VectorSpace (Average a)
- Data.Average: maybeAverage :: Fractional a => Average a -> Maybe a
- Data.Average: newtype Average a
- Data.Functor.Couple: instance Typeable2 Couple
- Data.Functor.Couple: instance Typeable2 Twain
- Data.Semigroup.Instances: instance Num a => Num (Product a)
- Data.Semigroup.Instances: instance Num a => Num (Sum a)
- Music.Score.Articulation: instance HasArticulation a b => HasArticulation (TremoloT a) (TremoloT b)
- Music.Score.Articulation: instance HasArticulations a b => HasArticulations (TremoloT a) (TremoloT b)
- Music.Score.Articulation: instance Typeable2 ArticulationT
- Music.Score.Convert: reactiveToVoice' :: Span -> Reactive a -> Voice a
- Music.Score.Convert: scoreToVoice :: Transformable a => Score a -> Voice (Maybe a)
- Music.Score.Convert: voiceToScore :: Voice a -> Score a
- Music.Score.Convert: voiceToScore' :: Voice (Maybe a) -> Score a
- Music.Score.Dynamics: data Ctxt a
- Music.Score.Dynamics: instance HasDynamic a b => HasDynamic (TremoloT a) (TremoloT b)
- Music.Score.Dynamics: instance HasDynamics a b => HasDynamics (TremoloT a) (TremoloT b)
- Music.Score.Dynamics: instance Typeable2 DynamicT
- Music.Score.Export.Lilypond: instance (HasDynamicNotation a b c, HasArticulationNotation c d e, Part e ~ Part c, HasOrdPart a, Transformable a, Semigroup a, Tiable e, HasOrdPart c, Show (Part c), HasLilypondInstrument (Part c)) => HasBackendScore Lilypond (Score a)
- Music.Score.Export.Midi: instance HasBackendNote Midi a => HasBackendNote Midi (DynamicT (Sum Double) a)
- Music.Score.Harmonics: instance Typeable1 HarmonicT
- Music.Score.Instances: instance (Monoid b, Alterable a) => Alterable (Couple b a)
- Music.Score.Instances: instance (Monoid b, Augmentable a) => Augmentable (Couple b a)
- Music.Score.Instances: instance (Monoid b, IsDynamics a) => IsDynamics (Couple b a)
- Music.Score.Instances: instance (Monoid b, IsPitch a) => IsPitch (Couple b a)
- Music.Score.Instances: instance (Monoid b, Reversible a) => Reversible (Couple b a)
- Music.Score.Instances: instance (Monoid b, Transformable a) => Transformable (Couple b a)
- Music.Score.Instances: instance Alterable a => Alterable (TremoloT a)
- Music.Score.Instances: instance Augmentable a => Augmentable (TremoloT a)
- Music.Score.Instances: instance HasHarmonic a => HasHarmonic (TremoloT a)
- Music.Score.Instances: instance HasSlide a => HasSlide (TremoloT a)
- Music.Score.Instances: instance HasText a => HasText (TremoloT a)
- Music.Score.Instances: instance IsDynamics a => IsDynamics (TremoloT a)
- Music.Score.Instances: instance IsPitch a => IsPitch (TremoloT a)
- Music.Score.Instances: instance Reversible a => Reversible (TremoloT a)
- Music.Score.Instances: instance Semigroup a => Semigroup (TremoloT a)
- Music.Score.Instances: instance Tiable a => Tiable (TremoloT a)
- Music.Score.Instances: instance Transformable a => Transformable (TremoloT a)
- Music.Score.Part: extractParts' :: (Ord (Part a), HasPart' a) => Score a -> [(Part a, Score a)]
- Music.Score.Part: extracted' :: (Ord (Part a), Ord (Part b), HasPart' a, HasPart' b) => Iso (Score a) (Score b) [(Part a, Score a)] [(Part b, Score b)]
- Music.Score.Part: instance Typeable2 PartT
- Music.Score.Phrases: mvoicePVoice :: Lens (MVoice a) (MVoice b) (PVoice a) (PVoice b)
- Music.Score.Phrases: unsafeMvoicePVoice :: Iso (MVoice a) (MVoice b) (PVoice a) (PVoice b)
- Music.Score.Pitch: augmentIntervals :: (HasPhrases' s a, Transposable a) => Interval a -> s -> s
- Music.Score.Pitch: highestPitch :: (HasPitches' a, Ord (Pitch a)) => a -> Pitch a
- Music.Score.Pitch: instance HasPitch a b => HasPitch (TremoloT a) (TremoloT b)
- Music.Score.Pitch: instance HasPitches a b => HasPitches (TremoloT a) (TremoloT b)
- Music.Score.Pitch: lowestPitch :: (HasPitches' a, Ord (Pitch a)) => a -> Pitch a
- Music.Score.Slide: instance Typeable1 SlideT
- Music.Score.Text: instance Typeable1 TextT
- Music.Score.Ties: instance Typeable1 TieT
- Music.Score.Tremolo: TremoloT :: Couple (Max Word) a -> TremoloT a
- Music.Score.Tremolo: getTremoloT :: TremoloT a -> Couple (Max Word) a
- Music.Score.Tremolo: instance Typeable1 TremoloT
- Music.Score.Tremolo: newtype TremoloT a
- Music.Time.Behavior: instance Typeable1 Behavior
- Music.Time.Bound: instance Typeable1 Bound
- Music.Time.Chord: instance Show a => Show (Chord a)
- Music.Time.Chord: instance Typeable1 Chord
- Music.Time.Delayed: instance Show a => Show (Delayed a)
- Music.Time.Delayed: instance Typeable1 Delayed
- Music.Time.Internal.Transform: instance Functor Product
- Music.Time.Internal.Transform: instance Functor Sum
- Music.Time.Internal.Transform: whilstM :: (Functor f, Transformable a, Transformable b) => (a -> f b) -> Span -> a -> f b
- Music.Time.Internal.Util: breakList :: Int -> [a] -> [a] -> [a]
- Music.Time.Internal.Util: composed :: [b -> b] -> b -> b
- Music.Time.Internal.Util: curry3 :: ((a, b, c) -> d) -> a -> b -> c -> d
- Music.Time.Internal.Util: divideList :: Int -> [a] -> [[a]]
- Music.Time.Internal.Util: dup :: a -> (a, a)
- Music.Time.Internal.Util: filterOnce :: (a -> Bool) -> [a] -> [a]
- Music.Time.Internal.Util: floor' :: RealFrac a => a -> a
- Music.Time.Internal.Util: mapF :: (b -> b) -> [b] -> [b]
- Music.Time.Internal.Util: mapFTL :: (a -> b) -> (a -> b) -> (a -> b) -> [a] -> [b]
- Music.Time.Internal.Util: mapIndexed :: (Int -> a -> b) -> [a] -> [b]
- Music.Time.Internal.Util: mapL :: (b -> b) -> [b] -> [b]
- Music.Time.Internal.Util: mapT :: (b -> b) -> [b] -> [b]
- Music.Time.Internal.Util: mapWithNext :: (a -> Maybe a -> b) -> [a] -> [b]
- Music.Time.Internal.Util: mapWithPrev :: (Maybe a -> a -> b) -> [a] -> [b]
- Music.Time.Internal.Util: mapWithPrevNext :: (Maybe a -> a -> Maybe a -> b) -> [a] -> [b]
- Music.Time.Internal.Util: merge :: Ord a => [a] -> [a] -> [a]
- Music.Time.Internal.Util: mergeBy :: (a -> a -> Ordering) -> [a] -> [a] -> [a]
- Music.Time.Internal.Util: mergeBy' :: (a -> a -> Bool) -> [a] -> [a] -> [a]
- Music.Time.Internal.Util: replic :: Integral a => a -> b -> [b]
- Music.Time.Internal.Util: retainUpdates :: Eq a => [a] -> [Maybe a]
- Music.Time.Internal.Util: rotated :: Int -> [a] -> [a]
- Music.Time.Internal.Util: rotl :: [a] -> [a]
- Music.Time.Internal.Util: rotr :: [a] -> [a]
- Music.Time.Internal.Util: rots :: [a] -> [[a]]
- Music.Time.Internal.Util: splitWhile :: (a -> Bool) -> [a] -> [[a]]
- Music.Time.Internal.Util: swap :: (a, b) -> (b, a)
- Music.Time.Internal.Util: toDouble :: Real a => a -> Double
- Music.Time.Internal.Util: tripl :: ((a, b), c) -> (a, b, c)
- Music.Time.Internal.Util: tripr :: (a, (b, c)) -> (a, b, c)
- Music.Time.Internal.Util: unRatio :: Integral a => Ratio a -> (a, a)
- Music.Time.Internal.Util: unf :: (a -> Maybe a) -> a -> [a]
- Music.Time.Internal.Util: untripl :: (a, b, c) -> ((a, b), c)
- Music.Time.Internal.Util: withNext :: [a] -> [(a, Maybe a)]
- Music.Time.Internal.Util: withPrev :: [a] -> [(Maybe a, a)]
- Music.Time.Meta: instance Typeable1 AddMeta
- Music.Time.Note: instance Typeable1 Note
- Music.Time.Reactive: instance Typeable1 Reactive
- Music.Time.Reverse: instance Typeable1 NoReverse
- Music.Time.Score: instance FoldableWithIndex Span NScore
- Music.Time.Score: instance FoldableWithIndex Span Score
- Music.Time.Score: instance FunctorWithIndex Span NScore
- Music.Time.Score: instance FunctorWithIndex Span Score
- Music.Time.Score: instance TraversableWithIndex Span NScore
- Music.Time.Score: instance TraversableWithIndex Span Score
- Music.Time.Score: instance Typeable1 NScore
- Music.Time.Score: instance Typeable1 Score
- Music.Time.Segment: instance Typeable1 Segment
- Music.Time.Stretched: instance Show a => Show (Stretched a)
- Music.Time.Stretched: instance Traversable (Couple a)
- Music.Time.Stretched: instance Typeable1 Stretched
- Music.Time.Track: instance Show a => Show (Track a)
- Music.Time.Track: instance Typeable1 Track
- Music.Time.Voice: instance Show a => Show (Voice a)
- Music.Time.Voice: instance Typeable1 Voice
+ Data.Functor.Couple: instance Traversable (Couple b)
+ Data.Functor.Couple: instance Traversable (Twain b)
+ Data.Functor.Couple: instance Typeable Couple
+ Data.Functor.Couple: instance Typeable Twain
+ Data.List.Ordered: Ordered :: Map a Positive -> Ordered a
+ Data.List.Ordered: elem :: Ord a => a -> Ordered a -> Bool
+ Data.List.Ordered: fromList :: Ord a => [a] -> Maybe (Ordered a)
+ Data.List.Ordered: getOrdered :: Ordered a -> Map a Positive
+ Data.List.Ordered: instance Comonad Max
+ Data.List.Ordered: instance Comonad Min
+ Data.List.Ordered: instance Ord a => Eq (Ordered a)
+ Data.List.Ordered: instance Ord a => Ord (Ordered a)
+ Data.List.Ordered: length :: Ordered a -> Int
+ Data.List.Ordered: map :: (Ord a, Ord b) => (a -> b) -> Ordered a -> Ordered b
+ Data.List.Ordered: newtype Ordered a
+ Data.List.Ordered: null :: Ordered k -> Bool
+ Data.List.Ordered: occs :: Ord a => a -> Ordered a -> Int
+ Data.List.Ordered: ordered :: Ord a => Prism' [a] (Ordered a)
+ Data.List.Ordered: toList :: Ordered a -> [a]
+ Data.List.Ordered: type Positive = Natural
+ Data.List.Ordered: unsafeFromList :: Ord a => [a] -> Ordered a
+ Data.List.Ordered: unsafeOrdered :: Ord a => Iso' [a] (Ordered a)
+ Music.Score.Articulation: addArtCon :: (HasPhrases s t a b, HasArticulation' a, HasArticulation a b, Articulation a ~ d, Articulation b ~ Ctxt d) => s -> t
+ Music.Score.Articulation: instance Typeable ArticulationT
+ Music.Score.Articulation: varticulation :: (HasArticulation a (SetArticulation a1 a), HasArticulation a a, Functor f, (~) * (Articulation (SetArticulation a1 a)) a1) => (Voice (Articulation a) -> f (Voice a1)) -> Voice a -> f (Voice (SetArticulation a1 a))
+ Music.Score.Color: colorBlack :: HasColor a => a -> a
+ Music.Score.Dynamics: instance Typeable DynamicT
+ Music.Score.Export.DynamicNotation: removeCloseDynMarks :: (HasPhrases' s a, HasDynamics' a, Dynamic a ~ DynamicNotation, a ~ SetDynamic (Dynamic a) a) => s -> s
+ Music.Score.Export.DynamicNotation: removeDynMark :: (HasDynamics' a, Dynamic a ~ DynamicNotation, a ~ SetDynamic (Dynamic a) a) => a -> a
+ Music.Score.Export.Lilypond: instance (HasDynamicNotation a b c, HasArticulationNotation c d e, Part e ~ Part c, HasOrdPart a, Transformable a, Semigroup a, Tiable e, HasOrdPart c, Show (Part c), HasLilypondInstrument (Part c), Satisfied) => HasBackendScore Lilypond (Score a)
+ Music.Score.Export.Midi: instance (Real d, HasBackendNote Midi a) => HasBackendNote Midi (DynamicT d a)
+ Music.Score.Harmonics: instance Typeable HarmonicT
+ Music.Score.Meta.Extract: attributionAt :: HasMeta a => Time -> String -> a -> Maybe String
+ Music.Score.Meta.Extract: attributionsAt :: HasMeta a => Time -> a -> [(String, Maybe String)]
+ Music.Score.Meta.Extract: commonMetaAt :: HasMeta a => Time -> a -> [(String, Maybe String)]
+ Music.Score.Meta.Extract: partNames :: (HasParts' a, Show (Part a)) => a -> [String]
+ Music.Score.Meta.Extract: titleAt :: HasMeta a => Time -> a -> Maybe Title
+ Music.Score.Meta.Pickup: data Pickup
+ Music.Score.Meta.Pickup: instance Default Pickup
+ Music.Score.Meta.Pickup: instance Eq Pickup
+ Music.Score.Meta.Pickup: instance Monoid Pickup
+ Music.Score.Meta.Pickup: instance Ord Pickup
+ Music.Score.Meta.Pickup: instance Semigroup Pickup
+ Music.Score.Meta.Pickup: instance Show Pickup
+ Music.Score.Meta.Pickup: instance Typeable Pickup
+ Music.Score.Meta.Tempo: adagio :: Tempo
+ Music.Score.Meta.Tempo: allegretto :: Tempo
+ Music.Score.Meta.Tempo: allegro :: Tempo
+ Music.Score.Meta.Tempo: andante :: Tempo
+ Music.Score.Meta.Tempo: largo :: Tempo
+ Music.Score.Meta.Tempo: lento :: Tempo
+ Music.Score.Meta.Tempo: moderato :: Tempo
+ Music.Score.Meta.Tempo: presto :: Tempo
+ Music.Score.Part: extractPartsWithInfo :: (Ord (Part a), HasPart' a) => Score a -> [(Part a, Score a)]
+ Music.Score.Part: extractedWithInfo :: (Ord (Part a), Ord (Part b), HasPart' a, HasPart' b) => Iso (Score a) (Score b) [(Part a, Score a)] [(Part b, Score b)]
+ Music.Score.Part: instance Typeable PartT
+ Music.Score.Phrases: mVoicePVoice :: Lens (MVoice a) (MVoice b) (PVoice a) (PVoice b)
+ Music.Score.Phrases: mVoiceTVoice :: Lens (MVoice a) (MVoice b) (TVoice a) (TVoice b)
+ Music.Score.Phrases: mapPhrasesWithPrevAndCurrentOnset :: HasPhrases s t a b => (Maybe Time -> Time -> Phrase a -> Phrase b) -> s -> t
+ Music.Score.Phrases: pVoiceTVoice :: Lens (PVoice a) (PVoice b) (TVoice a) (TVoice b)
+ Music.Score.Phrases: type TVoice a = Track (Phrase a)
+ Music.Score.Phrases: unsafeMVoicePVoice :: Iso (MVoice a) (MVoice b) (PVoice a) (PVoice b)
+ Music.Score.Pitch: highest :: (HasPitches' a, Ord (Pitch a)) => a -> Maybe (Pitch a)
+ Music.Score.Pitch: lowest :: (HasPitches' a, Ord (Pitch a)) => a -> Maybe (Pitch a)
+ Music.Score.Pitch: type AffinePair v w = (VectorSpace v, AffineSpace w)
+ Music.Score.Pitch: type PitchPair v w = (Num (Scalar v), IsInterval v, IsPitch w)
+ Music.Score.Slide: instance Typeable SlideT
+ Music.Score.Text: instance Typeable TextT
+ Music.Score.Text: textLast :: (HasPhrases' s a, HasText a) => String -> s -> s
+ Music.Score.Ties: instance Tiable a => Tiable (Average a)
+ Music.Score.Ties: instance Typeable TieT
+ Music.Score.Tremolo: data TremoloT a
+ Music.Score.Tremolo: instance (Monoid b, Alterable a) => Alterable (Couple b a)
+ Music.Score.Tremolo: instance (Monoid b, Augmentable a) => Augmentable (Couple b a)
+ Music.Score.Tremolo: instance (Monoid b, IsDynamics a) => IsDynamics (Couple b a)
+ Music.Score.Tremolo: instance (Monoid b, IsPitch a) => IsPitch (Couple b a)
+ Music.Score.Tremolo: instance (Monoid b, Reversible a) => Reversible (Couple b a)
+ Music.Score.Tremolo: instance (Monoid b, Transformable a) => Transformable (Couple b a)
+ Music.Score.Tremolo: instance Alterable a => Alterable (TremoloT a)
+ Music.Score.Tremolo: instance Augmentable a => Augmentable (TremoloT a)
+ Music.Score.Tremolo: instance HasArticulation a b => HasArticulation (TremoloT a) (TremoloT b)
+ Music.Score.Tremolo: instance HasArticulations a b => HasArticulations (TremoloT a) (TremoloT b)
+ Music.Score.Tremolo: instance HasDynamic a b => HasDynamic (TremoloT a) (TremoloT b)
+ Music.Score.Tremolo: instance HasDynamics a b => HasDynamics (TremoloT a) (TremoloT b)
+ Music.Score.Tremolo: instance HasHarmonic a => HasHarmonic (TremoloT a)
+ Music.Score.Tremolo: instance HasPitch a b => HasPitch (TremoloT a) (TremoloT b)
+ Music.Score.Tremolo: instance HasPitches a b => HasPitches (TremoloT a) (TremoloT b)
+ Music.Score.Tremolo: instance HasSlide a => HasSlide (TremoloT a)
+ Music.Score.Tremolo: instance HasText a => HasText (TremoloT a)
+ Music.Score.Tremolo: instance IsDynamics a => IsDynamics (TremoloT a)
+ Music.Score.Tremolo: instance IsPitch a => IsPitch (TremoloT a)
+ Music.Score.Tremolo: instance Reversible a => Reversible (TremoloT a)
+ Music.Score.Tremolo: instance Semigroup a => Semigroup (TremoloT a)
+ Music.Score.Tremolo: instance Tiable a => Tiable (Couple b a)
+ Music.Score.Tremolo: instance Tiable a => Tiable (TremoloT a)
+ Music.Score.Tremolo: instance Transformable a => Transformable (TremoloT a)
+ Music.Score.Tremolo: instance Typeable TremoloT
+ Music.Score.Tremolo: runTremoloT :: TremoloT a -> (Int, a)
+ Music.Time.Behavior: instance IsString a => IsString (Behavior a)
+ Music.Time.Behavior: instance Typeable Behavior
+ Music.Time.Bound: instance Typeable Bound
+ Music.Time.Chord: instance (Show a, Transformable a) => Show (Chord a)
+ Music.Time.Chord: instance IsString a => IsString (Chord a)
+ Music.Time.Chord: instance Typeable Chord
+ Music.Time.Chord: unchord :: Lens (Chord a) (Chord b) [Delayed a] [Delayed b]
+ Music.Time.Delayed: instance (Show a, Transformable a) => Show (Delayed a)
+ Music.Time.Delayed: instance IsString a => IsString (Delayed a)
+ Music.Time.Delayed: instance Typeable Delayed
+ Music.Time.Graces: Graces :: (Nominal f a, f a, Nominal f a) -> Graces f a
+ Music.Time.Graces: getGraces :: Graces f a -> (Nominal f a, f a, Nominal f a)
+ Music.Time.Graces: instance (Applicative f, Alternative f) => Applicative (Graces f)
+ Music.Time.Graces: instance Alternative f => Alternative (Nominal f)
+ Music.Time.Graces: instance Eq (f a) => Eq (Graces f a)
+ Music.Time.Graces: instance Foldable f => Foldable (Graces f)
+ Music.Time.Graces: instance Functor f => Functor (Graces f)
+ Music.Time.Graces: instance Ord (f a) => Ord (Graces f a)
+ Music.Time.Graces: instance Read (f a) => Read (Graces f a)
+ Music.Time.Graces: instance Show (f a) => Show (Graces f a)
+ Music.Time.Graces: instance Traversable f => Traversable (Graces f)
+ Music.Time.Graces: newtype Graces f a
+ Music.Time.Internal.Convert: reactiveToVoice' :: Span -> Reactive a -> Voice a
+ Music.Time.Internal.Convert: scoreToVoice :: Transformable a => Score a -> Voice (Maybe a)
+ Music.Time.Internal.Convert: voiceToScore :: Voice a -> Score a
+ Music.Time.Internal.Convert: voiceToScore' :: Voice (Maybe a) -> Score a
+ Music.Time.Internal.Transform: instance (Ord a, Transformable a) => Transformable (Set a)
+ Music.Time.Internal.Transform: itransformed :: (Transformable a, Transformable b) => Span -> Iso a b a b
+ Music.Time.Internal.Transform: whilstL2 :: (Transformable t, Transformable a, Functor f) => (t -> f a) -> (Span, t) -> f (Span, a)
+ Music.Time.Internal.Util: partial :: (a -> Bool) -> a -> Maybe a
+ Music.Time.Meta: getMeta :: HasMeta a => a -> Meta
+ Music.Time.Meta: instance Typeable AddMeta
+ Music.Time.Meta: mapMeta :: HasMeta a => (Meta -> Meta) -> a -> a
+ Music.Time.Meta: preserveMeta :: (HasMeta a, HasMeta b) => (a -> b) -> a -> b
+ Music.Time.Nominal: Nominal :: f a -> Nominal f a
+ Music.Time.Nominal: getNominal :: Nominal f a -> f a
+ Music.Time.Nominal: instance Applicative f => Applicative (Nominal f)
+ Music.Time.Nominal: instance Eq (f a) => Eq (Nominal f a)
+ Music.Time.Nominal: instance Foldable f => Foldable (Nominal f)
+ Music.Time.Nominal: instance Functor f => Functor (Nominal f)
+ Music.Time.Nominal: instance Monad f => Monad (Nominal f)
+ Music.Time.Nominal: instance Ord (f a) => Ord (Nominal f a)
+ Music.Time.Nominal: instance Read (f a) => Read (Nominal f a)
+ Music.Time.Nominal: instance Reversible (f a) => Reversible (Nominal f a)
+ Music.Time.Nominal: instance Show (f a) => Show (Nominal f a)
+ Music.Time.Nominal: instance Splittable (Nominal f a)
+ Music.Time.Nominal: instance Transformable (Nominal f a)
+ Music.Time.Nominal: instance Traversable f => Traversable (Nominal f)
+ Music.Time.Nominal: newtype Nominal f a
+ Music.Time.Note: instance IsDynamics a => IsDynamics (Note a)
+ Music.Time.Note: instance IsInterval a => IsInterval (Note a)
+ Music.Time.Note: instance IsPitch a => IsPitch (Note a)
+ Music.Time.Note: instance IsString a => IsString (Note a)
+ Music.Time.Note: instance Typeable Note
+ Music.Time.Past: Future :: (Max Time, a) -> Future a
+ Music.Time.Past: firstTrue :: [Maybe a] -> Maybe a
+ Music.Time.Past: future :: Future a -> Time -> Maybe a
+ Music.Time.Past: futureSeg :: Future (Segment a) -> Behavior (Maybe a)
+ Music.Time.Past: getFuture :: Future a -> (Max Time, a)
+ Music.Time.Past: indexPast :: [Past a] -> Time -> Maybe a
+ Music.Time.Past: instance Eq a => Eq (Future a)
+ Music.Time.Past: instance Eq a => Eq (Past a)
+ Music.Time.Past: instance Functor Future
+ Music.Time.Past: instance Functor Past
+ 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.Past: instance Ord a => Ord (Future a)
+ Music.Time.Past: instance Ord a => Ord (Past a)
+ Music.Time.Past: newtype Future a
+ Music.Time.Reactive: instance Typeable Reactive
+ Music.Time.Reverse: instance Typeable NoReverse
+ Music.Time.Score: eras :: Traversal' (Score a) Span
+ Music.Time.Score: instance (Show a, Transformable a) => Show (Score a)
+ Music.Time.Score: instance IsString a => IsString (Score a)
+ Music.Time.Score: instance Typeable NScore
+ Music.Time.Score: instance Typeable Score
+ Music.Time.Segment: instance Typeable Segment
+ Music.Time.Stretched: instance (Show a, Transformable a) => Show (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 Typeable Stretched
+ Music.Time.Track: instance (Show a, Transformable a) => Show (Track a)
+ Music.Time.Track: instance Typeable Track
+ Music.Time.Transform: conjugateS :: Span -> Span -> Span
+ Music.Time.Types: afterOffset :: Time -> Span -> Bool
+ Music.Time.Types: afterOnset :: Time -> Span -> Bool
+ Music.Time.Types: beforeOffset :: Time -> Span -> Bool
+ Music.Time.Types: beforeOnset :: Time -> Span -> Bool
+ Music.Time.Types: properlyEncloses :: Span -> Span -> Bool
+ Music.Time.Types: startsBefore :: Span -> Span -> Bool
+ Music.Time.Types: startsLater :: Span -> Span -> Bool
+ Music.Time.Types: startsWhenStarts :: Span -> Span -> Bool
+ Music.Time.Types: startsWhenStops :: Span -> Span -> Bool
+ Music.Time.Types: stopsAtTheSameTime :: Span -> Span -> Bool
+ Music.Time.Types: stopsBefore :: Span -> Span -> Bool
+ Music.Time.Types: stopsLater :: Span -> Span -> Bool
+ Music.Time.Types: stopsWhenStarts :: Span -> Span -> Bool
+ Music.Time.Types: stopsWhenStops :: Span -> Span -> Bool
+ Music.Time.Types: strictlyAfterOffset :: Time -> Span -> Bool
+ Music.Time.Types: strictlyAfterOnset :: Time -> Span -> Bool
+ Music.Time.Types: strictlyBeforeOffset :: Time -> Span -> Bool
+ Music.Time.Types: strictlyBeforeOnset :: Time -> Span -> Bool
+ Music.Time.Voice: durationsV :: Lens' (Voice a) [Duration]
+ Music.Time.Voice: instance (Show a, Transformable a) => Show (Voice a)
+ Music.Time.Voice: instance IsString a => IsString (Voice a)
+ Music.Time.Voice: instance Typeable Voice
+ Music.Time.Voice: valuesV :: Lens (Voice a) (Voice b) [a] [b]
- Data.Clipped: fromClipped :: (Num a, Ord a) => Clipped a -> a
+ Data.Clipped: fromClipped :: (Ord a, Num a) => Clipped a -> a
- Data.Clipped: unsafeToClipped :: (Num a, Ord a) => a -> Clipped a
+ Data.Clipped: unsafeToClipped :: (Ord a, Num a) => a -> Clipped a
- Music.Score.Export.Backend: type HasArticulationNotation a b c = (HasArticulation3 a b c, Articulation b ~ Ctxt (Articulation a), Articulation c ~ ArticulationNotation, Articulation a ~ (Sum Double, Sum Double))
+ Music.Score.Export.Backend: type HasArticulationNotation a b c = (HasArticulation3 a b c, Articulation b ~ Ctxt (Articulation a), Articulation c ~ ArticulationNotation, Articulation a ~ (Average Double, Average Double))
- Music.Score.Export.Lilypond: toLilypond :: HasLilypond a => a -> Music
+ Music.Score.Export.Lilypond: toLilypond :: HasLilypond a => a -> LyMusic
- Music.Score.Pitch: type Transposable a = (HasPitches a a, VectorSpace (Interval a), AffineSpace (Pitch a), IsInterval (Interval a), IsPitch (Pitch a), Num (Scalar (Interval a)))
+ Music.Score.Pitch: type Transposable a = (HasPitches' a, AffinePair (Interval a) (Pitch a), PitchPair (Interval a) (Pitch a))
- Music.Time.Chord: chord :: Lens (Chord a) (Chord b) [Delayed a] [Delayed b]
+ Music.Time.Chord: chord :: Getter [Delayed a] (Chord a)
- Music.Time.Internal.Transform: onSpan :: (Transformable a, Functor f) => LensLike' f a b -> Span -> LensLike' f a b
+ Music.Time.Internal.Transform: onSpan :: (Transformable s, Transformable t, Functor f) => LensLike f s t a b -> Span -> LensLike f s t a b
- Music.Time.Internal.Transform: spanned :: (Transformable a, Transformable b) => Span -> Lens 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.Internal.Transform: transformed :: Transformable a => Span -> Iso' a a
+ Music.Time.Internal.Transform: transformed :: (Transformable a, Transformable b) => Span -> Iso a b a b
- Music.Time.Past: Past :: (a, Time) -> Past a
+ Music.Time.Past: Past :: (Min Time, a) -> Past a
- Music.Time.Past: getPast :: Past a -> (a, Time)
+ Music.Time.Past: getPast :: Past a -> (Min Time, a)
- Music.Time.Transform: onSpan :: (Transformable a, Functor f) => LensLike' f a b -> Span -> LensLike' f a b
+ 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 a, Transformable b) => Span -> Lens a b 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: transformed :: Transformable a => Span -> Iso' a a
+ Music.Time.Transform: transformed :: (Transformable a, Transformable b) => Span -> Iso a b a b

Files

music-score.cabal view
@@ -1,6 +1,6 @@  name:                   music-score-version:                1.7.1+version:                1.7.2 author:                 Hans Hoglund maintainer:             Hans Hoglund license:                BSD3@@ -21,36 +21,35 @@   location:           git://github.com/music-suite/music-score.git    library-    build-depends:      base                    >= 4       && < 5,+    build-depends:      base                    >= 4 && < 5,                         aeson                   >= 0.7.0.6 && < 1,-                        lens                    >= 4.3 && < 4.4,+                        lens                    >= 4.3.3 && < 4.4,                         process                 >= 1.2 && < 1.3,                         containers,-                         void,                         nats,                                   data-default,+                        average                 >= 0.6 && < 1,                         semigroups              >= 0.13.0.1 && < 1,                         semigroupoids,-                        contravariant           >= 0.4.4 && < 1,-                        comonad,-                        bifunctors,-                        profunctors,-                        distributive,-                        adjunctions             >= 4.1 && < 5,+                        contravariant           >= 1.2 && < 2,+                        comonad                 >= 4.2.2 && < 5,+                        bifunctors              >= 4.1.1.1 && < 5,+                        profunctors             >= 4.2.0.1 && < 5,+                        distributive            >= 0.4.4 && < 5,+                        adjunctions             >= 4.2 && < 5,                         transformers            >= 0.3.0.0 && < 0.5,                         mtl                     >= 2.1.2 && < 2.3,                         monadplus,                         NumInstances,-                         colour                  >= 2.3.3 && < 3.0,                         HCodecs                 >= 0.5 && < 0.6,                         vector-space            >= 0.8.7 && < 0.9,                         vector-space-points     >= 0.2 && < 0.3,-                        musicxml2               == 1.7.1,-                        lilypond                == 1.7.1,-                        music-pitch-literal     == 1.7.1,-                        music-dynamics-literal  == 1.7.1,+                        musicxml2               == 1.7.2,+                        lilypond                == 1.7.2,+                        music-pitch-literal     == 1.7.2,+                        music-dynamics-literal  == 1.7.2,                          prettify,                         parsec@@ -59,10 +58,9 @@                         Data.Functor.Couple                         Data.Functor.Context                         Data.Functor.Rep.Lens+                        Data.List.Ordered                         Data.Semigroup.Instances-                        Data.Average                         Control.Monad.Compose-                        Control.Lens.Cons.Middle                         Music.Time                         Music.Time.Types                         Music.Time.Transform@@ -105,6 +103,8 @@                         Music.Score.Meta.Tempo                         Music.Score.Meta.Time                         Music.Score.Meta.Title+                        Music.Score.Meta.Pickup+                        Music.Score.Meta.Extract                         -- Music.Score.Clef                         Music.Score.Pitch                         Music.Score.Articulation@@ -126,9 +126,9 @@                         Music.Score.Import.Abc                         Music.Score.Import.Lilypond                         Music.Score.Import.Midi-                        Music.Score.Convert                         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
− src/Control/Lens/Cons/Middle.hs
@@ -1,9 +0,0 @@--module Control.Lens.Cons.Middle (-      _middle-  ) where--import Control.Lens--_middle :: (Snoc s s a a, Cons s s b b) => Traversal' s s-_middle = _tail._init
− src/Data/Average.hs
@@ -1,127 +0,0 @@--{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}--module Data.Average (-    Average(..),-    average,-    maybeAverage-  ) where--import Prelude hiding ((**))---- import Test.QuickCheck(Arbitrary(..))--import Data.Typeable-import Data.Maybe-import Data.Semigroup-import Data.AdditiveGroup-import Data.VectorSpace-import Data.AffineSpace-import Control.Monad-import Control.Applicative---- |--- A monoid for 'Average' values.------ This is actually just the free monoid with an extra function 'average' for--- extracing the (arithmetic) mean. This function is used to implement 'Real',--- so you can use 'Average' whenever a ('Monoid', 'Real') is required.------ >>> toRational $ mconcat [1,2::Average Rational]--- 3 % 2--- >>> toRational $ mconcat [1,2::Sum Rational]--- 3 % 1--- >>> toRational $ mconcat [1,2::Product Rational]--- 2 % 1----newtype Average a = Average { getAverage :: [a] }-  deriving (Show, {-Enum, Bounded,-} Semigroup, Monoid, -    Typeable, Functor, Applicative)--instance (Fractional a, Eq a) => Eq (Average a) where-  a == b = average a == average b--instance (Fractional a, Ord a) => Ord (Average a) where-  a `compare` b = average a `compare` average b-  --- What should (+) and (*) do for Average values?--- --- The important thing is to preserve scalar addition and multiplication (for example--- scaling all components of) an average value by some constant factor, so we can just as--- well use the standard list instance. What about averages with more components? I *think*--- 'average' is a linear map, so they would work as expected:--- --- >>> average (2<>2<>3)+average (3<>3)--- 16 % 3--- >>> average $ (2<>2<>3)+(3<>3)--- 16 % 3--- >>> average (mconcat [5,6,9])*average (mconcat[-1,0])--- (-10) % 3--- >>> average $ (mconcat [5,6,9])*(mconcat[-1,0])--- (-10) % 3--- --instance Num a => Num (Average a) where-  (+) = liftA2 (+)-  (*) = liftA2 (*)-  negate = fmap negate-  abs    = fmap abs-  signum = fmap signum-  fromInteger = pure . fromInteger-  -instance (Fractional a, Num a) => Fractional (Average a) where-  (/) = liftA2 (/)-  fromRational = pure . fromRational--instance (Real a, Fractional a) => Real (Average a) where-  toRational = toRational . average--instance Floating a => Floating (Average a) where-  pi = pure pi-  exp = fmap exp-  sqrt = fmap sqrt-  log = fmap log-  sin = fmap sin-  tan = fmap tan-  cos = fmap cos-  asin = fmap asin-  atan = fmap atan-  acos = fmap acos-  sinh = fmap sinh-  tanh = fmap tanh-  cosh = fmap cosh-  asinh = fmap asinh-  atanh = fmap atanh-  acosh = fmap acosh-  -instance AdditiveGroup a => AdditiveGroup (Average a) where-  zeroV = pure zeroV-  (^+^) = liftA2 (^+^)-  negateV = fmap negateV--instance VectorSpace a => VectorSpace (Average a) where-  type Scalar (Average a) = Scalar a-  s *^ v = liftA2 (*^) (pure s) v--instance AffineSpace a => AffineSpace (Average a) where-  type Diff (Average a) = Average (Diff a)-  p1 .-. p2 = liftA2 (.-.) p1 p2-  p .+^ v   = liftA2 (.+^) p v--{--instance Arbitrary a => Arbitrary (Average a) where-  arbitrary = fmap Average arbitrary--}---- | Return the average of all monoidal components. If given 'mempty', return zero.-average :: Fractional a => Average a -> a-average = fromMaybe 0 . maybeAverage---- | Return the average of all monoidal components. If given 'mempty', return 'Nothing'.-maybeAverage :: Fractional a => Average a -> Maybe a-maybeAverage (Average []) = Nothing-maybeAverage (Average xs) = Just $ sum xs / fromIntegral (length xs)--
src/Data/Functor/Couple.hs view
@@ -41,7 +41,7 @@ -- A variant of pair/writer with lifted instances for the numeric classes, using 'Applicative'. -- newtype Twain b a = Twain { getTwain :: (b, a) }-  deriving (Show, Functor, Foldable, Typeable, Applicative, Monad, Comonad, Semigroup, Monoid)+  deriving (Show, Functor, Traversable, Foldable, Typeable, Applicative, Monad, Comonad, Semigroup, Monoid)  instance Wrapped (Twain b a) where   type Unwrapped (Twain b a) = (b, a)@@ -116,7 +116,7 @@ -- A variant of pair/writer with lifted instances for the numeric classes, using 'Applicative'. -- newtype Couple b a = Couple { getCouple :: (b, a) }-  deriving (Show, Functor, Foldable, Typeable, Applicative, Monad, Comonad, Semigroup, Monoid)+  deriving (Show, Functor, Foldable, Traversable, Typeable, Applicative, Monad, Comonad, Semigroup, Monoid)  instance Wrapped (Couple b a) where   type Unwrapped (Couple b a) = (b, a)
+ src/Data/List/Ordered.hs view
@@ -0,0 +1,96 @@++{-# LANGUAGE RankNTypes                 #-}+{-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE ViewPatterns               #-}+{-# LANGUAGE CPP #-}++module Data.List.Ordered where++import           Control.Lens (Iso', iso, Prism', prism')+import           Control.Applicative+import           Control.Comonad+import           Data.Functor.Couple+import           Data.Ord            (comparing)+import           Data.List           (takeWhile, sort, sortBy, group)+import           Data.Maybe+import           Data.Semigroup+import           Control.Monad++import qualified Data.Set as Set+import qualified Data.Map as Map+import Numeric.Natural+++-- TODO full definition+type Positive = Natural+++-- TODO move+#ifndef GHCI+instance Comonad Min where+  extract (Min x) = x+  duplicate (Min x) = Min (Min x)+instance Comonad Max where+  extract (Max x) = x+  duplicate (Max x) = Max (Max x)+#endif++-- TODO move+-- TODO use positive+-- newtype Ordered a = Ordered { getOrdered :: Set.Set (a, Positive) }+-- OR+newtype Ordered a = Ordered { getOrdered :: {-Ord a =>-} Map.Map a Positive }+  deriving ({-, Foldable, Traversable-})++instance (Ord a) => Eq (Ordered a) where+  Ordered a == Ordered b = a == b++instance Ord a => Ord (Ordered a) where+  Ordered a < Ordered b = a < b++-- | Alas, not a functor+map :: (Ord a, Ord b) => (a -> b) -> Ordered a -> Ordered b+map f (Ordered m) = Ordered (Map.mapKeys f m)++toList :: Ordered a -> [a]+toList (Ordered xs) = concatMap (uncurry $ flip $ replicate . fromIntegral) $ Map.toList xs++unsafeFromList :: Ord a => [a] -> Ordered a+unsafeFromList = fromMaybe (error "unsafeFromList: Not sorted") . fromList++-- Safe (but slow) conversion from lists to ordered lists+fromList :: Ord a => [a] -> Maybe (Ordered a)+fromList xs+  | xs /= sort xs = Nothing+  | otherwise     = Just $ Ordered $ Map.fromList $ +    Prelude.map (\x -> (head x, fromIntegral $ Prelude.length x)) $ group xs++-- Safe (but slow) prism from lists to ordered lists+ordered :: Ord a => Prism' [a] (Ordered a)+ordered = prism' toList fromList+{-+  where+    prism' bs sma = prism bs (\s -> maybe (Left s) Right (sma s))+    prism bt seta = dimap seta (either pure (fmap bt)) . right'+-}++unsafeOrdered :: Ord a => Iso' [a] (Ordered a)+unsafeOrdered = iso unsafeFromList toList+{-+  where+    iso sa bt = dimap sa (fmap bt)+-}++elem :: Ord a => a -> Ordered a -> Bool+elem k = (> 0) . occs k    +    +occs :: Ord a => a -> Ordered a -> Int+occs k = maybe 0 fromIntegral . Map.lookup k . getOrdered++null :: Ordered k -> Bool+null = Map.null . getOrdered++length :: Ordered a -> Int+length = Prelude.length . toList+-- elem x (Ordered xs) = x
src/Data/Semigroup/Instances.hs view
@@ -16,9 +16,10 @@  -- TODO move these to semigroups and music-pitch-literal -#if (__GLASGOW_HASKELL__ < 781)+#if !MIN_VERSION_base(4,7,0) deriving instance Num a => Num (Sum a) #endif+ deriving instance Real a => Real (Sum a) deriving instance Fractional a => Fractional (Sum a) deriving instance AdditiveGroup a => AdditiveGroup (Sum a)@@ -33,9 +34,10 @@   Sum p .+^ Sum v = Sum (p .+^ v)  -#if (__GLASGOW_HASKELL__ < 781)+#if !MIN_VERSION_base(4,7,0) deriving instance Num a => Num (Product a) #endif+ deriving instance Real a => Real (Product a) deriving instance Fractional a => Fractional (Product a) deriving instance AdditiveGroup a => AdditiveGroup (Product a)@@ -48,6 +50,7 @@   type Diff (Product a) = Product (Diff a)   Product p .-. Product q = Product (p .-. q)   Product p .+^ Product v = Product (p .+^ v)+   deriving instance IsDynamics a => IsDynamics (Sum a)
src/Music/Score.hs view
@@ -9,8 +9,6 @@ -- Stability   : experimental -- Portability : non-portable (TF,GNTD) ----- Provides a musical score representation.--- -------------------------------------------------------------------------------------  module Music.Score (@@ -23,7 +21,6 @@         module Data.VectorSpace,         module Data.AffineSpace,         module Data.AffineSpace.Point,-        module Data.Average,          module Music.Time,         -- module Music.Score.Combinators,@@ -91,7 +88,6 @@ import           Data.Traversable import           Data.Typeable import           Data.VectorSpace               hiding (Sum, getSum)-import           Data.Average  import           Music.Time                     hiding (time) 
src/Music/Score/Articulation.hs view
@@ -70,18 +70,22 @@          -- * Articulation transformer         ArticulationT(..),++        -- * Context+        varticulation,+        addArtCon,   ) where  import           Control.Applicative import           Control.Comonad import           Control.Lens                  hiding (above, below, transform)-import           Control.Lens.Cons.Middle import           Data.AffineSpace import           Data.Foldable import           Data.Functor.Couple import           Data.Semigroup import           Data.Typeable import           Data.VectorSpace              hiding (Sum)+import           Data.Functor.Context  import           Music.Score.Part import           Music.Time@@ -95,7 +99,6 @@ import           Music.Score.Slide import           Music.Score.Text import           Music.Score.Ties-import           Music.Score.Tremolo   @@ -256,8 +259,6 @@  type instance Articulation (Couple c a)        = Articulation a type instance SetArticulation g (Couple c a)   = Couple c (SetArticulation g a)-type instance Articulation (TremoloT a)        = Articulation a-type instance SetArticulation g (TremoloT a)   = TremoloT (SetArticulation g a) type instance Articulation (TextT a)           = Articulation a type instance SetArticulation g (TextT a)      = TextT (SetArticulation g a) type instance Articulation (HarmonicT a)       = Articulation a@@ -272,11 +273,6 @@ instance (HasArticulation a b) => HasArticulation (Couple c a) (Couple c b) where   articulation = _Wrapped . articulation -instance (HasArticulations a b) => HasArticulations (TremoloT a) (TremoloT b) where-  articulations = _Wrapped . articulations-instance (HasArticulation a b) => HasArticulation (TremoloT a) (TremoloT b) where-  articulation = _Wrapped . articulation- instance (HasArticulations a b) => HasArticulations (TextT a) (TextT b) where   articulations = _Wrapped . articulations instance (HasArticulation a b) => HasArticulation (TextT a) (TextT b) where@@ -319,44 +315,9 @@     accentuation :: Lens' a (Accentuation a)     separation   :: Lens' a (Separation a) -{---- TODO move-instance Num () where-  _ + _ = ()-  _ - _ = ()-  _ * _ = ()-  signum _ = ()-  abs _ = ()-  fromInteger _ = ()--instance Fractional () where-  _ / _ = ()-  fromRational _ = ()--instance VectorSpace () where-  type Scalar () = ()-  _ *^ _ = ()--instance AffineSpace () where-  type Diff () = ()-  _ .-. _ = ()-  _ .+^ _ = ()--instance Articulated () where-  accentuation = id-  separation   = id--}- instance (AffineSpace a, AffineSpace b, Fractional a, Fractional b) => Articulated (a, b) where-  accentuation = _1'-  separation   = _2'--_1' :: Lens' (a, b) a-_1' = _1--_2' :: Lens' (a, b) b-_2' = _2-  +  accentuation = _1+  separation   = _2   accent :: (HasPhrases' s b, HasArticulations' b, Articulation b ~ a, Articulated a) => s -> s@@ -456,7 +417,6 @@ --     rem = liftA2 rem --     toInteger = toInteger . extract --- | Unsafe: Do not use 'Wrapped' instances instance Wrapped (ArticulationT p a) where   type Unwrapped (ArticulationT p a) = (p, a)   _Wrapped' = iso getArticulationT ArticulationT@@ -483,3 +443,12 @@     where       (a1,a2) = toTied a       (d1,d2) = toTied d+++-- TODO move+addArtCon :: (+  HasPhrases s t a b, HasArticulation' a, HasArticulation a b, Articulation a ~ d, Articulation b ~ Ctxt d+  ) => s -> t+addArtCon = over (phrases.varticulation) withContext+varticulation = lens (fmap $ view articulation) (flip $ zipVoiceWithNoScale (set articulation))+
src/Music/Score/Color.hs view
@@ -39,6 +39,7 @@         color,         colorRed,         colorBlue,+        colorBlack,          -- * Representation         ColorT(..),@@ -95,7 +96,6 @@ deriving instance Enum a => Enum (ColorT a) deriving instance Bounded a => Bounded (ColorT a) --- | Unsafe: Do not use 'Wrapped' instances instance Wrapped (ColorT a) where   type Unwrapped (ColorT a) = Couple (Option (Last (Colour Double))) a   _Wrapped' = iso getColorT ColorT@@ -118,11 +118,27 @@   -- |--- Set the number of tremolo divisions for all notes in the score.+-- Set color of all notes in the score. -- color :: HasColor a => Colour Double -> a -> a color = setColor +-- |+-- Color all notes in the score red.+--+colorRed :: HasColor a => a -> a colorRed = color C.red++-- |+-- Color all notes in the score blue.+--+colorBlue :: HasColor a => a -> a colorBlue = color C.blue++-- |+-- Color all notes in the score black.+--+colorBlack :: HasColor a => a -> a+colorBlack = color C.black+ 
− src/Music/Score/Convert.hs
@@ -1,179 +0,0 @@--{-# LANGUAGE ConstraintKinds            #-}-{-# LANGUAGE DeriveDataTypeable         #-}-{-# LANGUAGE DeriveFoldable             #-}-{-# LANGUAGE DeriveFunctor              #-}-{-# LANGUAGE FlexibleContexts           #-}-{-# LANGUAGE FlexibleInstances          #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE NoMonomorphismRestriction  #-}-{-# LANGUAGE TypeFamilies               #-}-{-# LANGUAGE ViewPatterns               #-}------------------------------------------------------------------------------------------ |--- Copyright   : (c) Hans Hoglund 2012-2014------ License     : BSD-style------ Maintainer  : hans@hanshoglund.se--- Stability   : experimental--- Portability : non-portable (TF,GNTD)------ Provides conversion betwen temporal container.------ /Warning/ This module will be removed soon.-------------------------------------------------------------------------------------------module Music.Score.Convert (-        voiceToScore,-        voiceToScore',-        scoreToVoice,-        reactiveToVoice',-  ) where--import           Control.Applicative-import           Control.Lens hiding (transform, time)-import           Control.Monad-import           Control.Monad.Plus-import           Data.AffineSpace-import           Data.AffineSpace.Point-import           Data.Foldable          (Foldable (..))-import           Data.Ord-import           Data.Ratio-import           Data.Semigroup-import           Data.String-import           Data.Traversable-import           Data.VectorSpace--import           Music.Score.Part-import           Music.Time-import           Music.Time.Reactive--import qualified Data.Foldable          as Foldable-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)-    where-        times = 0 : filter (\t -> u < t && t < v) (occs r)-        durs  = toRelativeTimeN' v times-{-# DEPRECATED reactiveToVoice' "" #-}---- |--- 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)-    where-       throwTime (t,d,x) = (d,x)-       addRests = concat . snd . mapAccumL g 0-           where-               g u (t, d, x)-                   | u == t    = (t .+^ d, [(t, d, Just x)])-                   | u <  t    = (t .+^ d, [(u, t .-. u, Nothing), (t, d, Just x)])-                   | 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)--}----- 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/Score/Dynamics.hs view
@@ -61,8 +61,6 @@         DynamicT(..),          -- * Context-        -- TODO move-        Ctxt,         vdynamic,         addDynCon, @@ -91,7 +89,6 @@ import           Music.Score.Slide import           Music.Score.Text import           Music.Score.Ties-import           Music.Score.Tremolo import           Music.Score.Internal.Util     (through) import           Music.Time import           Music.Time.Internal.Transform@@ -266,8 +263,6 @@  type instance Dynamic (Couple c a)        = Dynamic a type instance SetDynamic g (Couple c a)   = Couple c (SetDynamic g a)-type instance Dynamic (TremoloT a)        = Dynamic a-type instance SetDynamic g (TremoloT a)   = TremoloT (SetDynamic g a) type instance Dynamic (TextT a)           = Dynamic a type instance SetDynamic g (TextT a)      = TextT (SetDynamic g a) type instance Dynamic (HarmonicT a)       = Dynamic a@@ -285,13 +280,7 @@   dynamic = _Wrapped . dynamic  -instance (HasDynamics a b) => HasDynamics (TremoloT a) (TremoloT b) where-  dynamics = _Wrapped . dynamics -instance (HasDynamic a b) => HasDynamic (TremoloT a) (TremoloT b) where-  dynamic = _Wrapped . dynamic-- instance (HasDynamics a b) => HasDynamics (TextT a) (TextT b) where   dynamics = _Wrapped . dynamics @@ -376,7 +365,7 @@   HasPosition a, HasDynamics a a,    Dynamic a ~ Behavior c, Fractional c   ) => Duration -> a -> a-fadeIn d x = x & dynamics *~ (_onset x >-> d `transform` unit)+fadeIn d x = x & dynamics *~ ((_onset x >-> d) `transform` unit)  -- | -- Fade in.@@ -385,7 +374,7 @@   HasPosition a, HasDynamics a a,    Dynamic a ~ Behavior c, Fractional c   ) => Duration -> a -> a-fadeOut d x = x & dynamics *~ (d <-< _offset x `transform` rev unit)+fadeOut d x = x & dynamics *~ ((d <-< _offset x) `transform` rev unit)   @@ -437,7 +426,6 @@ --     rem = liftA2 rem --     toInteger = toInteger . extract --- | Unsafe: Do not use 'Wrapped' instances instance Wrapped (DynamicT p a) where   type Unwrapped (DynamicT p a) = (p, a)   _Wrapped' = iso getDynamicT DynamicT
src/Music/Score/Export/Backend.hs view
@@ -52,23 +52,22 @@ import qualified Data.Foldable import           Data.Functor.Couple import           Data.Maybe+import           Data.Monoid.Average import           Data.Ratio import           Data.Traversable              (Traversable, sequenceA) import qualified Music.Lilypond                as Lilypond import qualified Music.MusicXml.Simple         as MusicXml import           Music.Score.Internal.Export   hiding (MVoice)-import           Music.Time.Internal.Transform (whilstLD) import           System.Process import           Music.Time.Internal.Quantize import qualified Text.Pretty                   as Pretty import qualified Data.List-import           Music.Score.Convert (reactiveToVoice') -- TODO import           Music.Score.Internal.Util (composed, unRatio, swap, retainUpdates) import Music.Score.Export.DynamicNotation import Music.Score.Export.ArticulationNotation import Data.Semigroup import Data.Semigroup.Instances-+import Data.Functor.Context  import Music.Time import Music.Score.Dynamics@@ -106,7 +105,8 @@   Articulation b  ~ Ctxt (Articulation a),   Articulation c ~ ArticulationNotation,   -- TODO generalize-  Articulation a ~ (Sum Double, Sum Double)+  -- Articulated (Articulation a), Real (Separation (Articulation a)), Real (Accentuation (Articulation a))+  Articulation a ~ (Average Double, Average Double)  )  @@ -214,7 +214,5 @@ -- Backend developers are encouraged to provide wrappers on the form 'toX', 'writeX' etc. -- export :: (HasBackendScore b s, HasBackendNote b (BackendScoreEvent b s)) => b -> s -> BackendMusic b-export b = finalizeExport b . export'-  where-    export' = fmap (exportNote b) . exportScore b+export b = finalizeExport b . fmap (exportNote b) . exportScore b 
src/Music/Score/Export/DynamicNotation.hs view
@@ -34,13 +34,19 @@     CrescDim(..),     DynamicNotation(..),     notateDynamic,+    +    -- * Utility+    removeCloseDynMarks,+    removeDynMark,   ) where  import Data.Semigroup import Data.Functor.Context+import Data.AffineSpace import Control.Lens -- () import Music.Score.Dynamics import Music.Score.Ties+import Music.Score.Phrases import Music.Time  @@ -102,9 +108,17 @@     (EQ,EQ) -> ([],                   False)     (LT,GT) -> ([EndCresc, BeginDim], True)     (GT,LT) -> ([EndDim, BeginCresc], True)--   (Just x,  y, Nothing) -> case (x `compare` y) of     LT      -> ([EndCresc],   True)     EQ      -> ([],           False)     GT      -> ([EndDim],     True)+++removeCloseDynMarks :: (HasPhrases' s a, HasDynamics' a, Dynamic a ~ DynamicNotation, a ~ SetDynamic (Dynamic a) a) => s -> s+removeCloseDynMarks = mapPhrasesWithPrevAndCurrentOnset f+  where+    f Nothing t    = id+    f (Just t1) t2 = if (t2 .-. t1) > 1.5 then id else over (_head.mapped) removeDynMark++removeDynMark :: (HasDynamics' a, Dynamic a ~ DynamicNotation, a ~ SetDynamic (Dynamic a) a) => a -> a+removeDynMark x = set (dynamics' . _Wrapped' . _2) Nothing x
src/Music/Score/Export/Lilypond.hs view
@@ -1,4 +1,5 @@ +{-# LANGUAGE CPP                       #-} {-# LANGUAGE ConstraintKinds           #-} {-# LANGUAGE DefaultSignatures         #-} {-# LANGUAGE DeriveFoldable            #-}@@ -74,9 +75,7 @@ import           System.Process import qualified Text.Pretty                             as Pretty - import           Music.Dynamics.Literal-import qualified Music.Lilypond                          as Lilypond import           Music.Pitch.Literal import           Music.Score.Articulation import           Music.Score.Color@@ -101,6 +100,7 @@ import           Music.Time import           Music.Time.Internal.Quantize +import qualified Music.Lilypond                          as Lilypond   @@ -108,6 +108,12 @@   +#define COMPLEX_POLY_STUFF 1+++++ -- | -- Extract instrument info as per "Music.Part" -- This is really crude, needs rethinking!@@ -156,9 +162,9 @@  {- TODO move-instance Monoid Lilypond.Music where-  mempty      = pcatLy []-  mappend x y = pcatLy [x,y]+instance Monoid LyMusic where+  mempty      = pcatL []+  mappend x y = pcatL [x,y] -}  type LyMusic = Lilypond.Music@@ -171,8 +177,8 @@    finalizeExport _ = finalizeScore     where-      finalizeScore :: LyScore LyMusic -> Lilypond.Music-      finalizeScore (LyScore (info, x)) = pcatLy . map finalizeStaff $ x+      finalizeScore :: LyScore LyMusic -> LyMusic+      finalizeScore (LyScore (info, x)) = pcatL . map finalizeStaff $ x        -- TODO finalizeStaffGroup @@ -181,11 +187,11 @@         = addStaff         . addPartName (staffName info)         . addClef (staffClef info)-        . scatLy . map finalizeBar $ x+        . scatL . map finalizeBar $ x         where           addStaff                = Lilypond.New "Staff" Nothing-          addClef c x             = scatLy [Lilypond.Clef c, x]-          addPartName partName xs = scatLy [longName, shortName, xs]+          addClef c x             = scatL [Lilypond.Clef c, x]+          addPartName partName xs = scatL [longName, shortName, xs]             where               longName  = Lilypond.Set "Staff.instrumentName" (Lilypond.toValue partName)               shortName = Lilypond.Set "Staff.shortInstrumentName" (Lilypond.toValue partName)@@ -200,18 +206,19 @@           -- TODO rehearsal marks           -- TODO bar number change           -- TODO compound time signatures-          setTimeSignature (getTimeSignature -> (ms, n)) x = scatLy [Lilypond.Time (sum ms) n, x]+          setTimeSignature (getTimeSignature -> (ms, n)) x = scatL [Lilypond.Time (sum ms) n, x]        renderBarMusic :: Rhythm LyMusic -> LyMusic       renderBarMusic = go         where           go (Beat d x)            = Lilypond.removeSingleChords x           go (Dotted n (Beat d x)) = Lilypond.removeSingleChords x-          go (Group rs)            = scatLy $ map renderBarMusic rs+          go (Group rs)            = scatL $ map renderBarMusic rs           go (Tuplet m r)          = Lilypond.Times (realToFrac m) (renderBarMusic r)             where               (a,b) = bimap fromIntegral fromIntegral $ unRatio $ realToFrac m +#ifdef COMPLEX_POLY_STUFF instance (   HasDynamicNotation a b c,   HasArticulationNotation c d e,@@ -219,24 +226,46 @@   HasOrdPart a,   Transformable a,   Semigroup a,-  Tiable e,-  HasOrdPart c, Show (Part c), HasLilypondInstrument (Part c)+  Tiable e, HasOrdPart c, Show (Part c), +  HasLilypondInstrument (Part c),+  Satisfied   )   => HasBackendScore Lilypond (Score a) where+#else+instance (+  Tiable a, HasOrdPart a, Show (Part a), +  HasLilypondInstrument (Part a),+  Satisfied+  )+  => HasBackendScore Lilypond (Score a) where+#endif++#ifdef COMPLEX_POLY_STUFF   type BackendScoreEvent Lilypond (Score a) = SetArticulation ArticulationNotation (SetDynamic DynamicNotation a)+#else+  type BackendScoreEvent Lilypond (Score a) = a+#endif+   exportScore b score = LyScore     . (ScoreInfo,)+    -- Store time signatures etc for later use by finalizeScore     . map (uncurry $ exportPart timeSignatureMarks barDurations) +#ifdef COMPLEX_POLY_STUFF+    -- Notate articulation     . map (second $ over articulations notateArticulation)     . map (second $ preserveMeta addArtCon) +    -- Notate dynamics     . map (second $ removeCloseDynMarks)     . map (second $ over dynamics notateDynamic)     . map (second $ preserveMeta addDynCon) +    -- Merge simultaneous chords     . map (second $ preserveMeta simultaneous)-    . extractParts'+#endif++    . extractPartsWithInfo     $ normScore     where       (timeSignatureMarks, barDurations) = extractTimeSignatures normScore@@ -329,10 +358,10 @@ instance HasBackendNote Lilypond Integer where   -- TODO can we get rid of exportChord alltogether and just use LyContext?   exportNote  _ (LyContext d Nothing)    = (^*realToFrac (4*d)) Lilypond.rest-  exportNote  _ (LyContext d (Just x))   = (^*realToFrac (4*d)) $ Lilypond.note $ spellLy x+  exportNote  _ (LyContext d (Just x))   = (^*realToFrac (4*d)) $ Lilypond.note $ spellL x    exportChord _ (LyContext d Nothing)    = (^*realToFrac (4*d)) Lilypond.rest-  exportChord _ (LyContext d (Just xs))  = (^*realToFrac (4*d)) $ Lilypond.chord $ fmap spellLy xs+  exportChord _ (LyContext d (Just xs))  = (^*realToFrac (4*d)) $ Lilypond.chord $ fmap spellL xs  instance HasBackendNote Lilypond Int where   exportNote b = exportNote b . fmap toInteger@@ -364,6 +393,8 @@   exportNote b = exportNote b . fmap extract   exportChord b = exportChord b . fmap (fmap extract) ++#ifdef COMPLEX_POLY_STUFF instance HasBackendNote Lilypond a => HasBackendNote Lilypond (DynamicT DynamicNotation a) where   exportNote b = uncurry notate . getDynamicT . fmap (exportNote b) . sequenceA     where@@ -389,7 +420,12 @@        -- Use rcomposed as notateDynamic returns "mark" order, not application order       rcomposed = composed . reverse+#else+instance HasBackendNote Lilypond a => HasBackendNote Lilypond (DynamicT b a) where+  exportNote b = exportNote b . fmap extract+#endif +#ifdef COMPLEX_POLY_STUFF instance HasBackendNote Lilypond a => HasBackendNote Lilypond (ArticulationT ArticulationNotation a) where   exportNote b = uncurry notate . getArticulationT . fmap (exportNote b) . sequenceA     where@@ -413,6 +449,10 @@        -- Use rcomposed as notateDynamic returns "mark" order, not application order       rcomposed = composed . reverse+#else+instance HasBackendNote Lilypond a => HasBackendNote Lilypond (ArticulationT {-ArticulationNotation-}b a) where+  exportNote b = exportNote b . fmap extract     +#endif  instance HasBackendNote Lilypond a => HasBackendNote Lilypond (ColorT a) where   exportNote b = uncurry notate . getCouple . getColorT . fmap (exportNote b) . sequenceA@@ -436,44 +476,26 @@ instance HasBackendNote Lilypond a => HasBackendNote Lilypond (TremoloT a) where   -- TODO can this instance use the new shorter idiom?   exportNote b (LyContext d x) =-    fst (notate x d) $ exportNote b $ LyContext (snd $ notate x d) (fmap extract x)-    where-      notate Nothing d                               = (id, d)-      notate (Just (TremoloT (Couple (Max 0, _)))) d = (id, d)-      notate (Just (TremoloT (Couple (Max n, _)))) d = let-        scale   = 2^n-        newDur  = (d `min` (1/4)) / scale-        repeats = d / newDur-        in (Lilypond.Tremolo (round repeats), newDur)+    fst (notateTremolo x d) $ exportNote b $ LyContext (snd $ notateTremolo x d) (fmap extract x) + instance HasBackendNote Lilypond a => HasBackendNote Lilypond (TextT a) where-  exportNote b = uncurry notate . getCouple . getTextT . fmap (exportNote b) . sequenceA+  exportNote b = uncurry notateText . getCouple . getTextT . fmap (exportNote b) . sequenceA     where-      notate texts = composed (fmap Lilypond.addText texts) + instance HasBackendNote Lilypond a => HasBackendNote Lilypond (HarmonicT a) where-  exportNote b = uncurry notate . getCouple . getHarmonicT . fmap (exportNote b) . sequenceA-    where-      notate (Any isNat, Sum n) = case (isNat, n) of-        (_,     0) -> id-        (True,  n) -> notateNatural n-        (False, n) -> notateArtificial n-      notateNatural n = Lilypond.addFlageolet -- addOpen?-      notateArtificial n = id -- TODO+  exportNote b = uncurry notateHarmonic . getCouple . getHarmonicT . fmap (exportNote b) . sequenceA  instance HasBackendNote Lilypond a => HasBackendNote Lilypond (SlideT a) where   exportNote b  = uncurry notateGliss . getCouple . getSlideT . fmap (exportNote b) . sequenceA   exportChord b = uncurry notateGliss . getCouple . getSlideT . fmap (exportChord b) . sequenceA . fmap sequenceA -notateGliss ((Any eg, Any es),(Any bg, Any bs))-  | bg  = Lilypond.beginGlissando-  | bs  = Lilypond.beginGlissando-  | otherwise = id  {-   exportNote        :: b -> BC a   -> BN   exportChord       :: b -> BC [a] -> BN-  uncurry notateTie :: ((Any, Any), Lilypond.Music) -> Lilypond.Music+  uncurry notateTie :: ((Any, Any), LyMusic) -> LyMusic      BC (TieT a)        sequenceA   TieT (BC a)        fmap (exportNote b)@@ -490,6 +512,35 @@   exportNote b  = uncurry notateTie . getTieT . fmap (exportNote b) . sequenceA   exportChord b = uncurry notateTie . getTieT . fmap (exportChord b) . sequenceA . fmap sequenceA ++notateTremolo :: RealFrac b => Maybe (TremoloT a) -> b -> (LyMusic -> LyMusic, b)+notateTremolo Nothing d                        = (id, d)+notateTremolo (Just (runTremoloT -> (0, _))) d = (id, d)+notateTremolo (Just (runTremoloT -> (n, _))) d = let+  scale   = 2^n+  newDur  = (d `min` (1/4)) / scale+  repeats = d / newDur+  in (Lilypond.Tremolo (round repeats), newDur)++notateText :: [String] -> LyMusic -> LyMusic+notateText texts = composed (fmap Lilypond.addText texts)++notateHarmonic :: (Eq t, Num t) => (Any, Sum t) -> LyMusic -> LyMusic+notateHarmonic (Any isNat, Sum n) = case (isNat, n) of+  (_,     0) -> id+  (True,  n) -> notateNatural n+  (False, n) -> notateArtificial n+  where+    notateNatural n = Lilypond.addFlageolet -- addOpen?+    notateArtificial n = id -- TODO++notateGliss :: ((Any, Any), (Any, Any)) -> LyMusic -> LyMusic+notateGliss ((Any eg, Any es),(Any bg, Any bs))+  | bg  = Lilypond.beginGlissando+  | bs  = Lilypond.beginGlissando+  | otherwise = id++notateTie :: (Any, Any) -> LyMusic -> LyMusic notateTie (Any ta, Any tb)   | ta && tb  = Lilypond.beginTie   | tb        = Lilypond.beginTie@@ -502,17 +553,16 @@ type HasLilypond a = (HasBackendNote Lilypond (BackendScoreEvent Lilypond a), HasBackendScore Lilypond a)  -- |--- Convert a score to a Lilypond string.----toLilypondString :: HasLilypond a => a -> String-toLilypondString = show . Pretty.pretty . toLilypond---- | -- Convert a score to a Lilypond representation. ---toLilypond :: HasLilypond a => a -> Lilypond.Music+toLilypond :: HasLilypond a => a -> LyMusic toLilypond = export (undefined::Lilypond) +-- |+-- Convert a score to a Lilypond string.+--+toLilypondString :: HasLilypond a => a -> String+toLilypondString = show . Pretty.pretty . toLilypond  -- | -- Convert a score to a Lilypond representaiton and print it on the standard output.@@ -600,7 +650,8 @@   runLilypond >> cleanLilypond >> runOpen     where       runLilypond = void $ runCommand-        "lilypond -f pdf test.ly"  >>= waitForProcess+        -- "lilypond -f pdf test.ly"  >>= waitForProcess+        "lilypond -f pdf test.ly 2>/dev/null"  >>= waitForProcess       cleanLilypond = void $ runCommand         "rm -f test-*.tex test-*.texi test-*.count test-*.eps test-*.pdf test.eps"       runOpen = void $ runCommand@@ -633,123 +684,38 @@   --- TODO move-addArtCon :: (-  HasPhrases s t a b, HasArticulation a a, HasArticulation a b,-  Articulation a ~ d, Articulation b ~ Ctxt d-  ) => s -> t-addArtCon = over (phrases.varticulation) withContext-varticulation = lens (fmap $ view articulation) (flip $ zipVoiceWithNoScale (set articulation)) -removeCloseDynMarks :: (HasPhrases' s a, HasDynamics' a, Dynamic a ~ DynamicNotation, a ~ SetDynamic (Dynamic a) a) => s -> s-removeCloseDynMarks = mapPhrasesWithPrevAndCurrentOnset f-  where-    f Nothing t    = id-    f (Just t1) t2 = if (t2 .-. t1) > 1.5 then id else over (_head.mapped) removeDynMark -removeDynMark :: (HasDynamics' a, Dynamic a ~ DynamicNotation, a ~ SetDynamic (Dynamic a) a) => a -> a-removeDynMark x = set (dynamics' . _Wrapped' . _2) Nothing x --- type PVoice a = [Either Duration (Phrase a)]-type TVoice a = Track (Phrase a) --- foo :: HasPhrases' s a => s -> [TVoice a]-mapPhrasesWithPrevAndCurrentOnset :: HasPhrases s t a b => (Maybe Time -> Time -> Phrase a -> Phrase b) -> s -> t-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)--mVoiceTVoice :: Lens (MVoice a) (MVoice b) (TVoice a) (TVoice b)-mVoiceTVoice = mvoicePVoice . pVoiceTVoice--pVoiceTVoice :: Lens (PVoice a) (PVoice b) (TVoice a) (TVoice b)-pVoiceTVoice = lens pVoiceToTVoice (flip tVoiceToPVoice)-  where-    pVoiceToTVoice :: PVoice a -> TVoice a-    pVoiceToTVoice x = mkTrack $ rights $ map (sequenceA) $ mapZip (offsetPoints (0::Time)) (withDurationR x)--    -- TODO assert no overlapping-    tVoiceToPVoice :: TVoice a -> PVoice b -> PVoice a-    tVoiceToPVoice tv pv = set _rights newPhrases pv-      where-        newPhrases = toListOf traverse tv---_rights :: Lens [Either a b] [Either a c] [b] [c]-_rights = lens _rightsGet (flip _rightsSet)--_rightsGet :: [Either a b] -> [b]-_rightsGet = rights--_rightsSet :: [c] -> [Either a b] -> [Either a c]-_rightsSet cs = sndMapAccumL f cs-  where-    f cs     (Left a)  = (cs, Left a)-    f (c:cs) (Right b) = (cs, Right c)-    f []     (Right _) = error "No more cs"--sndMapAccumL f z = snd . Data.List.mapAccumL f z---- unsafePVoiceTVoice :: Iso (PVoice a) (PVoice b) (TVoice a) (TVoice b)--- unsafePVoiceTVoice = iso pVoiceToTVoice tVoiceToPVoice---   where---     pVoiceToTVoice :: PVoice a -> TVoice a---     pVoiceToTVoice x = mkTrack $ rights $ map (sequenceA) $ mapZip (offsetPoints (0::Time)) (withDurationR x)------     -- TODO assert no overlapping---     tVoiceToPVoice :: TVoice a -> PVoice a---     tVoiceToPVoice = undefined---mapZip :: ([a] -> [b]) -> [(a,c)] -> [(b,c)]-mapZip f = uncurry zip . first f . unzipR--mkTrack :: [(Time, a)] -> Track a-mkTrack = view track . map (view delayed)--withDurationR :: (Functor f, HasDuration a) => f a -> f (Duration, a)-withDurationR = fmap $ \x -> (_duration x, x)---- TODO generalize and move-mapWithDuration :: HasDuration a => (Duration -> a -> b) -> a -> b-mapWithDuration = over dual withDurationL . uncurry-  where-    withDurationL :: (Contravariant f, HasDuration a) => f (Duration, a) -> f a-    withDurationL = contramap $ \x -> (_duration x, x)--    dual :: Iso (a -> b) (c -> d) (Op b a) (Op d c)-    dual = iso Op getOp--dursToVoice :: [Duration] -> Voice ()-dursToVoice = mconcat . map (\d -> stretch d $ return ())---- *Music.Score.Export.Lilypond> print $ view (mVoiceTVoice) $ (fmap Just (dursToVoice [1,2,1]) <> return Nothing <> return (Just ()))                                                                             --- TODO This function is a workaround--- Whenever it is used, we should make the original function preserve meta instead-preserveMeta :: (HasMeta a, HasMeta b) => (a -> b) -> a -> b-preserveMeta f x = let m = view meta x in set meta m (f x)--pcatLy :: [Lilypond.Music] -> Lilypond.Music-pcatLy = pcatLy' False+pcatL :: [LyMusic] -> LyMusic+pcatL = pcatL' False -pcatLy' :: Bool -> [Lilypond.Music] -> Lilypond.Music-pcatLy' p = foldr Lilypond.simultaneous (Lilypond.Simultaneous p [])+pcatL' :: Bool -> [LyMusic] -> LyMusic+pcatL' p = foldr Lilypond.simultaneous (Lilypond.Simultaneous p []) -scatLy :: [Lilypond.Music] -> Lilypond.Music-scatLy = foldr Lilypond.sequential (Lilypond.Sequential [])+scatL :: [LyMusic] -> LyMusic+scatL = foldr Lilypond.sequential (Lilypond.Sequential []) -spellLy :: Integer -> Lilypond.Note-spellLy a = Lilypond.NotePitch (spellLy' a) Nothing+spellL :: Integer -> Lilypond.Note+spellL a = Lilypond.NotePitch (spellL' a) Nothing -spellLy' :: Integer -> Lilypond.Pitch-spellLy' p = Lilypond.Pitch (+spellL' :: Integer -> Lilypond.Pitch+spellL' p = Lilypond.Pitch (   toEnum $ fromIntegral pc,   fromIntegral alt,   fromIntegral oct   )   where (pc,alt,oct) = spellPitch (p + 72)++-- | A constraint that is always satisfied.+type Satisfied = (() ~ ())++-- | A constraint that is never satisfied.+type Unsatisfied = (() ~ Bool)+ 
src/Music/Score/Export/Midi.hs view
@@ -1,3 +1,4 @@+ {-# LANGUAGE TupleSections              #-} {-# LANGUAGE ViewPatterns               #-} {-# LANGUAGE ConstraintKinds            #-}@@ -54,12 +55,10 @@ import qualified Music.Lilypond                as Lilypond import qualified Music.MusicXml.Simple         as MusicXml import           Music.Score.Internal.Export   hiding (MVoice)-import           Music.Time.Internal.Transform (whilstLD) import           System.Process import           Music.Time.Internal.Quantize import qualified Text.Pretty                   as Pretty import qualified Data.List-import Music.Score.Convert (reactiveToVoice') -- TODO import           Music.Score.Internal.Util (composed, unRatio, swap, retainUpdates) import Music.Score.Export.DynamicNotation import Data.Semigroup.Instances@@ -190,7 +189,7 @@  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)) $ extractParts' $ fixTempo xs)+  exportScore _ xs = MidiScore (map (\(p,sc) -> ((getMidiChannel p, getMidiProgram p), fmap Identity sc)) $ extractPartsWithInfo $ fixTempo 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@@ -218,11 +217,11 @@   exportChord b = exportChord b . fmap (fmap (! 0))  -instance HasBackendNote Midi a => HasBackendNote Midi (DynamicT (Sum Double) a) where+instance (Real d, HasBackendNote Midi a) => HasBackendNote Midi (DynamicT d a) where   -- TODO   -- We have not standarized dynamic levels   -- Assume for now -6.5 to 6.5 where (-3.5 is ppp, -0.5 is mp, 0.5 is mf, 3.5 is fff etc)-  exportNote b (Identity (DynamicT (Sum d, x))) = setV (dynLevel d) <$> exportNote b (Identity x)+  exportNote b (Identity (DynamicT (realToFrac -> d, x))) = setV (dynLevel d) <$> exportNote b (Identity x)   dynLevel :: Double -> Midi.Velocity
src/Music/Score/Export/MusicXml.hs view
@@ -1,20 +1,20 @@ -{-# LANGUAGE TupleSections              #-}-{-# LANGUAGE ViewPatterns               #-}-{-# LANGUAGE ConstraintKinds            #-}-{-# LANGUAGE DefaultSignatures          #-}-{-# LANGUAGE DeriveFoldable             #-}-{-# LANGUAGE DeriveFunctor              #-}-{-# LANGUAGE DeriveTraversable          #-}-{-# LANGUAGE FlexibleContexts           #-}-{-# LANGUAGE FlexibleInstances          #-}-{-# LANGUAGE MultiParamTypeClasses      #-}-{-# LANGUAGE NoMonomorphismRestriction  #-}-{-# LANGUAGE OverloadedStrings          #-}-{-# LANGUAGE RankNTypes                 #-}-{-# LANGUAGE StandaloneDeriving         #-}-{-# LANGUAGE TypeFamilies               #-}-{-# LANGUAGE UndecidableInstances       #-}+{-# LANGUAGE ConstraintKinds           #-}+{-# LANGUAGE DefaultSignatures         #-}+{-# LANGUAGE DeriveFoldable            #-}+{-# LANGUAGE DeriveFunctor             #-}+{-# LANGUAGE DeriveTraversable         #-}+{-# LANGUAGE FlexibleContexts          #-}+{-# LANGUAGE FlexibleInstances         #-}+{-# LANGUAGE MultiParamTypeClasses     #-}+{-# LANGUAGE NoMonomorphismRestriction #-}+{-# LANGUAGE OverloadedStrings         #-}+{-# LANGUAGE RankNTypes                #-}+{-# LANGUAGE StandaloneDeriving        #-}+{-# LANGUAGE TupleSections             #-}+{-# LANGUAGE TypeFamilies              #-}+{-# LANGUAGE UndecidableInstances      #-}+{-# LANGUAGE ViewPatterns              #-}  ------------------------------------------------------------------------------------- -- |@@ -34,75 +34,74 @@     MusicXml,     XmlContext(..),     HasMusicXml,-    +     -- ** Converting to MusicXml     toMusicXml,-    toMusicXmlString,    -    +    toMusicXmlString,+     -- ** MusicXml I/O     showMusicXml,     openMusicXml,     writeMusicXml,   ) where -import           Music.Dynamics.Literal-import           Music.Pitch.Literal-import qualified Codec.Midi                    as Midi-import           Control.Comonad               (Comonad (..), extract)+import qualified Codec.Midi                              as Midi import           Control.Applicative+import           Control.Comonad                         (Comonad (..), extract)+import           Control.Lens                            hiding (rewrite)+import           Control.Monad+import           Data.AffineSpace import           Data.Bifunctor-import           Data.Colour.Names             as Color+import           Data.Colour.Names                       as Color import           Data.Default-import           Data.Foldable                 (Foldable)+import           Data.Foldable                           (Foldable) import qualified Data.Foldable import           Data.Functor.Couple+import           Data.Functor.Identity+import qualified Data.List import           Data.Maybe import           Data.Ratio-import           Data.Traversable              (Traversable, sequenceA)-import qualified Music.Lilypond                as Lilypond-import qualified Music.MusicXml.Simple         as MusicXml-import           Music.Score.Internal.Export   hiding (MVoice)-import           Music.Time.Internal.Transform (whilstLD)+import           Data.Semigroup+import           Data.Semigroup.Instances+import           Data.Traversable                        (Traversable,+                                                          sequenceA)+import           Data.VectorSpace                        hiding (Sum (..)) import           System.Process-import           Music.Time.Internal.Quantize-import qualified Text.Pretty                   as Pretty-import qualified Data.List-import Music.Score.Convert (reactiveToVoice') -- TODO-import           Music.Score.Internal.Util (composed, unRatio, swap, retainUpdates)-import Music.Score.Export.DynamicNotation-import Music.Score.Export.ArticulationNotation-import Data.Semigroup.Instances -import Music.Score.Export.Backend -import Data.Functor.Identity-import Data.Semigroup-import Control.Monad-import Data.VectorSpace hiding (Sum(..))-import Data.AffineSpace-import Control.Lens hiding (rewrite)--- import Control.Lens.Operators hiding ((|>))+import           Music.Dynamics.Literal+import           Music.Pitch.Literal+import           Music.Score.Articulation+import           Music.Score.Color+import           Music.Time.Internal.Convert             (reactiveToVoice')+import           Music.Score.Dynamics+import           Music.Score.Export.ArticulationNotation+import           Music.Score.Export.Backend+import           Music.Score.Export.DynamicNotation+import           Music.Score.Harmonics+import           Music.Score.Internal.Export             hiding (MVoice)+import           Music.Score.Internal.Util               (composed,+                                                          retainUpdates, swap,+                                                          unRatio)+import           Music.Score.Meta+import           Music.Score.Meta.Attribution+import           Music.Score.Meta.Tempo+import           Music.Score.Meta.Time+import           Music.Score.Meta.Title+import           Music.Score.Part+import           Music.Score.Phrases+import           Music.Score.Slide+import           Music.Score.Text+import           Music.Score.Ties+import           Music.Score.Tremolo+import           Music.Time+import           Music.Time.Internal.Quantize -import Music.Time-import Music.Score.Meta-import Music.Score.Meta.Title-import Music.Score.Meta.Attribution-import Music.Score.Dynamics-import Music.Score.Articulation-import Music.Score.Part-import Music.Score.Tremolo-import Music.Score.Text-import Music.Score.Harmonics-import Music.Score.Slide-import Music.Score.Color-import Music.Score.Ties-import Music.Score.Export.Backend-import Music.Score.Meta.Time-import Music.Score.Meta.Tempo-import Music.Score.Phrases+import qualified Text.Pretty                             as Pretty+import qualified Music.MusicXml.Simple                   as MusicXml  --- | +-- | -- Extract instrument info as per "Music.Part" -- This is really crude, needs rethinking! --@@ -112,7 +111,7 @@   --- TODO move +-- TODO move deriving instance Show MusicXml.Line deriving instance Show MusicXml.ClefSign -- deriving instance Eq MusicXml.PartList@@ -129,7 +128,7 @@ -- | A token to represent the MusicXml backend. data MusicXml -data ScoreInfo = ScoreInfo { scoreTitle :: String,+data ScoreInfo = ScoreInfo { scoreTitle    :: String,                              scoreComposer :: String,                              scorePartList :: MusicXml.PartList,                              scoreTempo    :: Tempo@@ -137,10 +136,10 @@   deriving (Eq, Show)  -data StaffInfo = StaffInfo { staffClef :: (MusicXml.ClefSign, MusicXml.Line) } +data StaffInfo = StaffInfo { staffClef :: (MusicXml.ClefSign, MusicXml.Line) }   deriving (Eq, Show) -data BarInfo = BarInfo { x_barTimeSignature :: Maybe TimeSignature } +data BarInfo = BarInfo { x_barTimeSignature :: Maybe TimeSignature }   deriving (Eq, Show)  -- | Hierachical representation of a MusicXml score.@@ -153,7 +152,7 @@   deriving (Functor, Eq, Show)  -- | A bar is a sequential composition of chords/notes/rests.-data XmlBar a = XmlBar { getXmlBar :: (BarInfo, Rhythm a) } +data XmlBar a = XmlBar { getXmlBar :: (BarInfo, Rhythm a) }   deriving (Functor, Eq, Show)  -- | Context passed to the note export.@@ -175,8 +174,8 @@     where  finalizeScore :: XmlScore MusicXml.Music -> MusicXml.Score-finalizeScore (XmlScore (info, x)) -  = MusicXml.fromParts title composer partList +finalizeScore (XmlScore (info, x))+  = MusicXml.fromParts title composer partList   . map (finalizeStaff tempo) $ x   where     title    = scoreTitle info@@ -187,8 +186,8 @@ -- TODO finalizeStaffGroup  finalizeStaff :: Tempo -> XmlStaff MusicXml.Music -> [MusicXml.Music]-finalizeStaff tempo (XmlStaff (info, x)) -  = id +finalizeStaff tempo (XmlStaff (info, x))+  = id   -- Staff name is not added here as MusicXML uses a separate part list   . addStartInfo   . addClef (staffClef info)@@ -218,15 +217,15 @@  finalizeBar :: XmlBar MusicXml.Music -> MusicXml.Music finalizeBar (XmlBar (BarInfo timeSignature, x))-  = maybe id setBarTimeSignature timeSignature +  = maybe id setBarTimeSignature timeSignature   . renderBarMusic $ x   where     -- TODO key signatures     -- TODO rehearsal marks     -- TODO bar number change     -- TODO compound time signatures-    setBarTimeSignature (getTimeSignature -> (ms, n)) x = mconcat [MusicXml.time (fromIntegral $ sum ms) (fromIntegral n), x]    -          +    setBarTimeSignature (getTimeSignature -> (ms, n)) x = mconcat [MusicXml.time (fromIntegral $ sum ms) (fromIntegral n), x]+ renderBarMusic :: Rhythm MusicXml.Music -> MusicXml.Music renderBarMusic = go   where@@ -248,13 +247,13 @@   )   => HasBackendScore MusicXml (Score a) where   type BackendScoreEvent MusicXml (Score a) = SetDynamic DynamicNotation a-  exportScore b score = XmlScore +  exportScore b score = XmlScore     . (ScoreInfo title composer partList tempo,)     . map (uncurry $ exportPart timeSignatureMarks barDurations)-    . map (second (over dynamics notateDynamic)) +    . map (second (over dynamics notateDynamic))     . map (second (preserveMeta addDynCon))-    . map (second (preserveMeta simultaneous)) -    . extractParts'+    . map (second (preserveMeta simultaneous))+    . extractPartsWithInfo     . normalizeScore     $ score     where@@ -262,46 +261,46 @@       composer = fromMaybe "" $ flip getAttribution "composer" $ metaAtStart score       partList = MusicXml.partList (fmap show $ allParts score)       tempo    = (metaAtStart score :: Tempo)-      (timeSignatureMarks, barDurations) = extractTimeSignatures score +      (timeSignatureMarks, barDurations) = extractTimeSignatures score         -- | Export a score as a single part. Overlapping notes will cause an error.       exportPart :: (         Tiable a,         HasMusicXmlInstrument (Part a)-        ) -        => [Maybe TimeSignature] -        -> [Duration] -        -> Part a -        -> Score a +        )+        => [Maybe TimeSignature]+        -> [Duration]+        -> Part a+        -> Score a         -> XmlStaff (XmlContext a) -      exportStaff :: Tiable a -        => [Maybe TimeSignature] -        -> [Duration] +      exportStaff :: Tiable a+        => [Maybe TimeSignature]+        -> [Duration]         -> Int    -- ^ clef, as per Music.Parts-        -> MVoice a +        -> MVoice a         -> XmlStaff (XmlContext a) -      exportBar :: Tiable a -        => Maybe TimeSignature -        -> MVoice a +      exportBar :: Tiable a+        => Maybe TimeSignature+        -> MVoice a         -> XmlBar (XmlContext a) -      quantizeBar :: Tiable a -        => MVoice a +      quantizeBar :: Tiable a+        => MVoice a         -> Rhythm (XmlContext a)        exportPart timeSignatureMarks barDurations part         = exportStaff timeSignatureMarks barDurations (getMusicXmlClef part)         . view singleMVoice -      exportStaff timeSignatures barDurations clefId -        = XmlStaff +      exportStaff timeSignatures barDurations clefId+        = XmlStaff         . addStaffInfo-        . zipWith exportBar timeSignatures +        . zipWith exportBar timeSignatures         . splitIntoBars barDurations-        where         +        where           clef = case clefId of             0 -> (MusicXml.GClef, 2)             1 -> (MusicXml.CClef, 3)@@ -310,11 +309,11 @@           splitIntoBars = splitTiesVoiceAt        exportBar timeSignature-        = XmlBar -        . addBarInfo +        = XmlBar+        . addBarInfo         . quantizeBar        where-         addBarInfo = (,) $ BarInfo timeSignature+         addBarInfo = (,) $ BarInfo timeSignature        quantizeBar = mapWithDur XmlContext . rewrite . handleErrors . quantize . view eventsV         where@@ -327,7 +326,7 @@ {-   Note:     We want all note transformers to be applicative morphisms, i.e.-      +       notate (pure x)   = pure (notate x)      Specifically@@ -339,8 +338,8 @@       exportNote b = uncurry notate . fmap (exportNote b) . getTieT . sequenceA     The latter looks a lot like cotraverse. Generalization?-   -      ++ -}  instance HasBackendNote MusicXml a => HasBackendNote MusicXml [a] where@@ -349,7 +348,7 @@ instance HasBackendNote MusicXml Integer where   -- TODO can we get rid of exportChord alltogether and just use XmlContext?   exportNote  _ (XmlContext d Nothing)    = MusicXml.rest (realToFrac d)-  exportNote  _ (XmlContext d (Just x))   = (`MusicXml.note` realToFrac d)  . spellMusicXml . fromIntegral $ x+  exportNote  _ (XmlContext d (Just x))   = (`MusicXml.note` realToFrac d)  . spellMusicXml . fromIntegral $ x    exportChord _ (XmlContext d Nothing)    = MusicXml.rest (realToFrac d)   exportChord _ (XmlContext d (Just xs))  = (`MusicXml.chord` realToFrac d) . fmap (spellMusicXml . fromIntegral) $ xs@@ -390,8 +389,8 @@ instance HasBackendNote MusicXml a => HasBackendNote MusicXml (DynamicT DynamicNotation a) where   exportNote b = uncurry notate . fmap (exportNote b) . getDynamicT . sequenceA     where-      notate (DynamicNotation (crescDims, level)) -        = composed (fmap notateCrescDim crescDims) +      notate (DynamicNotation (crescDims, level))+        = composed (fmap notateCrescDim crescDims)         . notateLevel level        notateCrescDim crescDims = case crescDims of@@ -405,7 +404,7 @@       notateLevel showLevel = case showLevel of          Nothing -> id          Just lvl -> (<>) $ MusicXml.dynamic (fromDynamics (DynamicsL (Just (fixLevel . realToFrac $ lvl), Nothing)))-      +       fixLevel :: Double -> Double       fixLevel x = fromIntegral (round (x - 0.5)) + 0.5 @@ -419,7 +418,7 @@   --     notate (ArticulationNotation (slurs, marks))   --       = composed (fmap notateMark marks)   --       . composed (fmap notateSlur slurs)-  -- +  --   --     notateMark mark = case mark of   --       NoMark         -> id   --       Staccato       -> MusicXml.staccato@@ -427,7 +426,7 @@   --       Marcato        -> MusicXml.strongAccent   --       Accent         -> MusicXml.accent   --       Tenuto         -> MusicXml.tenuto-  -- +  --   --     notateSlur slurs = case slurs of   --       NoSlur    -> id   --       BeginSlur -> MusicXml.beginSlur@@ -442,7 +441,7 @@       -- TODO handle any color       notate (Option Nothing)             = id       notate (Option (Just (Last color))) = \x -> MusicXml.Sequential [-        MusicXml.Override "NoteHead#' color" +        MusicXml.Override "NoteHead#' color"           (MusicXml.toLiteralValue $ "#" ++ colorName color),         x,         MusicXml.Revert "NoteHead#' color"@@ -455,12 +454,12 @@         | otherwise        = error "MusicXml backend: Unkown color" -} instance HasBackendNote MusicXml a => HasBackendNote MusicXml (TremoloT a) where-  exportNote b = uncurry notate . fmap (exportNote b) . getCouple . getTremoloT . sequenceA+  exportNote b = uncurry notate . fmap (exportNote b) . runTremoloT . sequenceA     where-      notate (Max n) = case n of+      notate n = case n of         0 -> id         n -> MusicXml.tremolo (fromIntegral n)-    + instance HasBackendNote MusicXml a => HasBackendNote MusicXml (TextT a) where   exportNote b = uncurry notate . fmap (exportNote b) . getCouple . getTextT . sequenceA     where@@ -480,8 +479,8 @@       -- Most programs do not recognize the harmonic tag       -- We set a single diamond notehead instead, which can be manually replaced       notateArtificial n = id -- TODO-       + instance HasBackendNote MusicXml a => HasBackendNote MusicXml (SlideT a) where   exportNote b = uncurry notateX . fmap (exportNote b) . getCouple . getSlideT . sequenceA     where@@ -551,11 +550,5 @@     fromIntegral oct     )     where (pc,alt,oct) = spellPitch (p + 60)---- TODO This function is a workaround--- Whenever it is used, we should make the original function preserve meta instead-preserveMeta :: (HasMeta a, HasMeta b) => (a -> b) -> a -> b-preserveMeta f x = let m = view meta x in set meta m (f x) -- End internal- 
src/Music/Score/Export/NoteList.hs view
@@ -52,12 +52,10 @@ import qualified Music.Lilypond                as Lilypond import qualified Music.MusicXml.Simple         as MusicXml import           Music.Score.Internal.Export   hiding (MVoice)-import           Music.Time.Internal.Transform (whilstLD) import           System.Process import           Music.Time.Internal.Quantize import qualified Text.Pretty                   as Pretty import qualified Data.List-import Music.Score.Convert (reactiveToVoice') -- TODO import           Music.Score.Internal.Util (composed, unRatio, swap, retainUpdates) import Music.Score.Export.DynamicNotation import Data.Semigroup.Instances
src/Music/Score/Export/SuperCollider.hs view
@@ -60,12 +60,10 @@ import qualified Music.Lilypond                as Lilypond import qualified Music.MusicXml.Simple         as MusicXml import           Music.Score.Internal.Export   hiding (MVoice)-import           Music.Time.Internal.Transform (whilstLD) import           System.Process import           Music.Time.Internal.Quantize import qualified Text.Pretty                   as Pretty import qualified Data.List-import Music.Score.Convert (reactiveToVoice') -- TODO import           Music.Score.Internal.Util (composed, unRatio, swap, retainUpdates) import Music.Score.Export.DynamicNotation import Data.Semigroup.Instances
src/Music/Score/Harmonics.hs view
@@ -24,8 +24,6 @@ -- -- Provides a representation of harmonics.  ----- /Warning/ This module is experimental.--- -------------------------------------------------------------------------------------  module Music.Score.Harmonics (@@ -84,8 +82,6 @@   setNatural b = fmap (setNatural b)   setHarmonic n = fmap (setHarmonic n) ---- | Unsafe: Do not use 'Wrapped' instances instance Wrapped (HarmonicT a) where   type Unwrapped (HarmonicT a) = Couple (Any, Sum Int) a   _Wrapped' = iso getHarmonicT HarmonicT
src/Music/Score/Instances.hs view
@@ -21,8 +21,7 @@ -- Stability   : experimental -- Portability : non-portable (TF,GNTD) ----- Instances for note transformers. This module should be imported as part--- of "Music.Score".+-- Provides miscellaneous instances. -- ------------------------------------------------------------------------------------- @@ -34,7 +33,7 @@ import           Control.Monad import           Data.AffineSpace import           Data.Default-import           Data.Average+import           Data.Monoid.Average import           Data.Foldable import           Data.Functor.Adjunction  (unzipR) import           Data.Functor.Couple@@ -45,6 +44,7 @@ import           Data.Typeable import           Data.VectorSpace hiding (Sum) import           Data.Semigroup.Instances+import           Data.Functor.Context  import           Music.Dynamics.Literal import           Music.Pitch.Alterable@@ -78,8 +78,6 @@     (<>) = liftA2 (<>) instance Semigroup a => Semigroup (TextT a) where     (<>) = liftA2 (<>)-instance Semigroup a => Semigroup (TremoloT a) where-    (<>) = liftA2 (<>) instance Semigroup a => Semigroup (PartT n a) where     PartT (v1,x1) <> PartT (v2,x2) = PartT (v1, x1 <> x2) @@ -179,15 +177,8 @@ deriving instance HasSlide a => HasSlide (TieT a) deriving instance HasText a => HasText (TieT a) -instance Tiable a => Tiable (TremoloT a) where-    toTied = unzipR . fmap toTied -type instance Part (TremoloT a) = Part a-deriving instance HasHarmonic a => HasHarmonic (TremoloT a)-deriving instance HasSlide a => HasSlide (TremoloT a)-deriving instance HasText a => HasText (TremoloT a) - -- TextT  instance Tiable a => Tiable (TextT a) where@@ -218,15 +209,7 @@   -deriving instance (Monoid b, IsPitch a) => IsPitch (Couple b a)-deriving instance (Monoid b, IsDynamics a) => IsDynamics (Couple b a)-deriving instance (Monoid b, Transformable a) => Transformable (Couple b a)-deriving instance (Monoid b, Reversible a) => Reversible (Couple b a)-deriving instance (Monoid b, Alterable a) => Alterable (Couple b a)-deriving instance (Monoid b, Augmentable a) => Augmentable (Couple b a) -deriving instance IsPitch a => IsPitch (TremoloT a)-deriving instance IsDynamics a => IsDynamics (TremoloT a) deriving instance IsPitch a => IsPitch (TextT a) deriving instance IsDynamics a => IsDynamics (TextT a) deriving instance IsPitch a => IsPitch (HarmonicT a)@@ -248,22 +231,18 @@ deriving instance Transformable a => Transformable (SlideT a) deriving instance Transformable a => Transformable (HarmonicT a) deriving instance Transformable a => Transformable (TextT a)-deriving instance Transformable a => Transformable (TremoloT a)  deriving instance Reversible a => Reversible (SlideT a) deriving instance Reversible a => Reversible (HarmonicT a) deriving instance Reversible a => Reversible (TextT a)-deriving instance Reversible a => Reversible (TremoloT a)  deriving instance Alterable a => Alterable (SlideT a) deriving instance Alterable a => Alterable (HarmonicT a) deriving instance Alterable a => Alterable (TextT a)-deriving instance Alterable a => Alterable (TremoloT a)  deriving instance Augmentable a => Augmentable (SlideT a) deriving instance Augmentable a => Augmentable (HarmonicT a) deriving instance Augmentable a => Augmentable (TextT a)-deriving instance Augmentable a => Augmentable (TremoloT a)   
src/Music/Score/Internal/Export.hs view
@@ -50,7 +50,7 @@ import           Data.VectorSpace  import           Music.Score.Articulation-import           Music.Score.Convert      (reactiveToVoice', scoreToVoice)+import           Music.Time.Internal.Convert import           Music.Score.Dynamics import           Music.Score.Part import           Music.Score.Pitch
src/Music/Score/Meta.hs view
@@ -22,10 +22,6 @@ -- Stability   : experimental -- Portability : non-portable (TF,GNTD) ----- Combinators for manipulating scores and related structures.------ /Warning/ This module is experimental.--- -------------------------------------------------------------------------------------  module Music.Score.Meta (
+ src/Music/Score/Meta/Extract.hs view
@@ -0,0 +1,63 @@++{-# LANGUAGE FlexibleContexts #-}++-- Utility to extract meta-data at a specific point in time.+module Music.Score.Meta.Extract where++import Control.Lens+import Control.Monad++import Music.Score.Meta.Attribution+import Music.Score.Meta.Title+import Music.Score.Meta.Time+import Music.Score.Meta.Key+-- import Music.Score.Meta.Pickup+import Music.Score.Meta.Tempo+import Music.Score.Part++import Music.Time+import Music.Time.Meta++attributionAt :: HasMeta a => Time -> String -> a -> Maybe String+attributionAt t n x = join+  $ fmap (`getAttribution` n)+  $ fmap (`atTime` t)+  $ unwrapMeta+  $ x^.meta++-- TODO get all *set* attributions+attributionsAt :: HasMeta a => Time -> a -> [(String, Maybe String)]+attributionsAt t x = [+  ("composer", attributionAt t "composer" x),+  ("lyricist", attributionAt t "lyricist" x)+  -- TODO etc+  ]++-- TODO rename getTitleAt etc in Meta.Title to prevent confunsion+titleAt :: HasMeta a => Time -> a -> Maybe Title+titleAt _ _ = Nothing++-- TODO key++-- TODO time++-- TODO tempo++partNames :: (HasParts' a, Show (Part a)) => a -> [String]+partNames = fmap show . toListOf parts'++commonMetaAt :: HasMeta a => Time -> a -> [(String, Maybe String)]+commonMetaAt t x = +  ("title", join $ fmap getTitle1 $ titleAt t x) +  : ("subtitle", join $ fmap getTitle2 $ titleAt t x) +  : ("subsubtitle", join $ fmap getTitle3 $ titleAt t x) +  : attributionsAt t x+  where+    getTitle1 = (`getTitleAt` 0)+    getTitle2 = (`getTitleAt` 1)+    getTitle3 = (`getTitleAt` 2)++--     >>> commonMetaAt 0 $ asScore $ composer "Hans" $ lyricist "Sondheim" c    +--     [("title",Nothing),("subtitle",Nothing),("subsubtitle",Nothing),("composer",Just "Hans"),("lyricist",Just "Sondheim")]++
+ src/Music/Score/Meta/Pickup.hs view
@@ -0,0 +1,98 @@++{-# LANGUAGE ConstraintKinds            #-}+{-# LANGUAGE DeriveDataTypeable         #-}+{-# LANGUAGE DeriveFoldable             #-}+{-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE DeriveTraversable          #-}+{-# LANGUAGE FlexibleContexts           #-}+{-# LANGUAGE FlexibleInstances          #-}+{-# LANGUAGE GADTs                      #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses      #-}+{-# LANGUAGE ScopedTypeVariables        #-}+{-# LANGUAGE TypeFamilies               #-}++-------------------------------------------------------------------------------------+-- |+-- Copyright   : (c) Hans Hoglund 2012-2014+--+-- License     : BSD-style+--+-- Maintainer  : hans@hanshoglund.se+-- Stability   : experimental+-- Portability : non-portable (TF,GNTD)+--+-- Provides tempo meta-data.+--+-- /Warning/ This is not supported by any backends yet.+--+-------------------------------------------------------------------------------------++module Music.Score.Meta.Pickup (+        -- * Pickup type+        Pickup,+        +        -- TODO++  ) where+++import           Control.Lens              (view)+import           Control.Monad.Plus+import           Data.Default+import           Data.Foldable             (Foldable)+import qualified Data.Foldable             as F+import qualified Data.List                 as List+import           Data.Map                  (Map)+import qualified Data.Map                  as Map+import           Data.Maybe+import           Data.Semigroup+import           Data.Set                  (Set)+import qualified Data.Set                  as Set+import           Data.String+import           Data.Traversable          (Traversable)+import qualified Data.Traversable          as T+import           Data.Typeable+import           Data.Void++import           Music.Pitch.Literal+import           Music.Score.Meta+import           Music.Score.Part+import           Music.Score.Pitch+import           Music.Score.Internal.Util+import           Music.Time+import           Music.Time.Reactive++-- | Represents a rehearsal mark.+--+-- TODO this needs zero-duration spans to work properly.+data Pickup = Pickup (Maybe String) Int+    deriving (Eq, Ord, Typeable)+-- name level(0=standard)++instance Default Pickup where+    def = Pickup Nothing 0++instance Semigroup Pickup where+    Pickup n1 l1 <> Pickup n2 l2 = Pickup (n1 <> n2) (l1 `max` l2)++instance Monoid Pickup where+    mempty  = def+    mappend = (<>)++instance Show Pickup where+    show (Pickup name level) = "A" -- TODo+++-- metronome :: Duration -> Bpm -> Tempo+-- 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++rehearsalMarkDuring :: HasMeta a => Span -> Pickup -> a -> a+rehearsalMarkDuring s x = addMetaNote $ view note (s, x)++withPickup :: (Pickup -> Score a -> Score a) -> Score a -> Score a+withPickup = withMeta+
src/Music/Score/Meta/Tempo.hs view
@@ -42,6 +42,16 @@         tempo,         tempoDuring, +        -- ** Common tempi+        presto,+        allegro,+        allegretto,+        moderato,+        andante,+        adagio,+        largo,+        lento,+                 -- * Extracting tempo         renderTempo,   ) where@@ -308,6 +318,16 @@   -}++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+   -- TODO consolidate
src/Music/Score/Part.hs view
@@ -49,10 +49,10 @@          -- * Extracting parts         extracted,-        extracted',+        extractedWithInfo,         extractPart,         extractParts,-        extractParts',+        extractPartsWithInfo,          -- * Manipulating parts @@ -240,14 +240,14 @@ filterPart :: (MonadPlus f, HasPart a a) => (Part a -> Bool) -> f a -> f a filterPart p = mfilter (\x -> p (x ^. part)) -extractParts' :: (Ord (Part a), HasPart' a) => Score a -> [(Part a, Score a)]-extractParts' x = zip (allParts x) (extractParts x)+extractPartsWithInfo :: (Ord (Part a), HasPart' a) => Score a -> [(Part a, Score a)]+extractPartsWithInfo x = zip (allParts x) (extractParts x)  extracted :: (Ord (Part a), HasPart' a{-, HasPart a b-}) => Iso (Score a) (Score b) [Score a] [Score b] extracted = iso extractParts mconcat -extracted' :: (Ord (Part a), Ord (Part b), HasPart' a, HasPart' b) => Iso (Score a) (Score b) [(Part a, Score a)] [(Part b, Score b)]-extracted' = iso extractParts' $ mconcat . fmap (uncurry $ set parts')+extractedWithInfo :: (Ord (Part a), Ord (Part b), HasPart' a, HasPart' b) => Iso (Score a) (Score b) [(Part a, Score a)] [(Part b, Score b)]+extractedWithInfo = iso extractPartsWithInfo $ mconcat . fmap (uncurry $ set parts')   @@ -255,7 +255,6 @@   deriving (Eq, Ord, Show, Typeable, Functor,     Applicative, Comonad, Monad, Transformable) --- | Unsafe: Do not use 'Wrapped' instances instance Wrapped (PartT p a) where   type Unwrapped (PartT p a) = (p, a)   _Wrapped' = iso getPartT PartT
src/Music/Score/Phrases.hs view
@@ -24,8 +24,6 @@ -- -- This module provides phrase-wise traversal. ----- /Warning/ This module is experimental.--- -------------------------------------------------------------------------------------  module Music.Score.Phrases (@@ -39,26 +37,54 @@     Phrase,     MVoice,     PVoice,+    TVoice,      -- ** Utility-    mvoicePVoice,-    unsafeMvoicePVoice,+    mVoicePVoice,+    mVoiceTVoice,+    pVoiceTVoice,+    unsafeMVoicePVoice,     singleMVoice,+    mapPhrasesWithPrevAndCurrentOnset,   ) where  import           Control.Applicative-import           Control.Exception   (assert)+import           Control.Applicative+import           Control.Comonad            (Comonad (..), extract)+import           Control.Exception          (assert) import           Control.Lens+import           Control.Lens               hiding (rewrite)+import           Control.Monad import           Control.Monad.Plus import           Data.AffineSpace-import qualified Data.List           as List+import           Data.AffineSpace+import           Data.Bifunctor+import           Data.Colour.Names          as Color+import           Data.Default+import           Data.Either+import           Data.Either+import           Data.Foldable              (Foldable)+import           Data.Functor.Adjunction    (unzipR)+import           Data.Functor.Context+import           Data.Functor.Contravariant+import           Data.Functor.Couple+import qualified Data.List                  as List+import qualified Data.List import           Data.Maybe+import           Data.Maybe import           Data.Ord+import           Data.Ratio import           Data.Semigroup+import           Data.Semigroup+import           Data.Traversable+import           Data.Traversable           (Traversable, sequenceA)+import           Data.VectorSpace           hiding (Sum (..))+import           System.Process  import           Music.Score.Part-import           Music.Score.Convert import           Music.Time+import           Music.Time.Internal.Convert+import           Music.Time.Internal.Util   -- |@@ -106,7 +132,7 @@   -- | Traverses all phrases in a voice. instance HasPhrases (PVoice a) (PVoice b) a b where   -- Note: This is actually OK in 'phr', as that just becomes (id . each . _Right)-  mvoices = from unsafeMvoicePVoice+  mvoices = from unsafeMVoicePVoice  -- | Traverses all phrases in each voice, using 'extracted'. instance (HasPart' a, {-HasPart a b, -}{-Transformable a,-} Ord (Part a)) =>@@ -119,7 +145,7 @@ Phrase traversal for score:  phrasesS :: (Ord (Part a), HasPart' a, Transformable a) => Traversal' (Score a) (Phrase a)-phrasesS = extracted . each . singleMVoice . mvoicePVoice . each . _Right+phrasesS = extracted . each . singleMVoice . mVoicePVoice . each . _Right  More generally: -}@@ -134,14 +160,13 @@ -- A generic phrase-traversal. -- phrases :: HasPhrases s t a b => Traversal s t (Phrase a) (Phrase b)-phrases = mvoices . mvoicePVoice . each . _Right+phrases = mvoices . mVoicePVoice . each . _Right  -- | -- View an 'MVoice' as a 'PVoice'. ---mvoicePVoice :: Lens (MVoice a) (MVoice b) (PVoice a) (PVoice b)-mvoicePVoice = unsafeMvoicePVoice--- TODO rename mVoicePVoice!+mVoicePVoice :: Lens (MVoice a) (MVoice b) (PVoice a) (PVoice b)+mVoicePVoice = unsafeMVoicePVoice -- TODO meta  -- |@@ -149,9 +174,8 @@ -- -- This a valid 'Iso' up to meta-data equivalence. ---unsafeMvoicePVoice :: Iso (MVoice a) (MVoice b) (PVoice a) (PVoice b)-unsafeMvoicePVoice = iso mvoiceToPVoice pVoiceToMVoice--- TODO rename unsafeMVoicePVoice!+unsafeMVoicePVoice :: Iso (MVoice a) (MVoice b) (PVoice a) (PVoice b)+unsafeMVoicePVoice = iso mvoiceToPVoice pVoiceToMVoice   where     mvoiceToPVoice :: MVoice a -> PVoice a     mvoiceToPVoice =@@ -177,12 +201,8 @@     phraseToVoice = fmap Just  --- -- TODO failure--- TODO why Transformable?-singleMVoice :: {-Transformable a =>-} Prism (Score a) (Score b) (MVoice a) (MVoice b)+singleMVoice :: Prism (Score a) (Score b) (MVoice a) (MVoice b) singleMVoice = iso scoreToVoice voiceToScore'   where     scoreToVoice :: {-Transformable a =>-} Score a -> MVoice a@@ -207,13 +227,71 @@     voiceToScore' = mcatMaybes . voiceToScore  --- instance (Transformable a, Transformable b) => Cons (Phrase a) (Phrase b) a b where-  -- _Cons = undefined--- instance (Transformable a, Transformable b) => Snoc (Phrase a) (Phrase b) a b where-  -- _Snoc = prism' pure (preview lastV)+-- foo :: HasPhrases' s a => s -> [TVoice a]+mapPhrasesWithPrevAndCurrentOnset :: HasPhrases s t a b => (Maybe Time -> Time -> Phrase a -> Phrase b) -> s -> t+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) --- TODO move+mVoiceTVoice :: Lens (MVoice a) (MVoice b) (TVoice a) (TVoice b)+mVoiceTVoice = mVoicePVoice . pVoiceTVoice++pVoiceTVoice :: Lens (PVoice a) (PVoice b) (TVoice a) (TVoice b)+pVoiceTVoice = lens pVoiceToTVoice (flip tVoiceToPVoice)+  where+    pVoiceToTVoice :: PVoice a -> TVoice a+    pVoiceToTVoice x = mkTrack $ rights $ map (sequenceA) $ firsts (offsetPoints (0::Time)) (withDurationR x)++    -- TODO assert no overlapping+    tVoiceToPVoice :: TVoice a -> PVoice b -> PVoice a+    tVoiceToPVoice tv pv = set _rights newPhrases pv+      where+        newPhrases = toListOf traverse tv+++_rights :: Lens [Either a b] [Either a c] [b] [c]+_rights = lens _rightsGet (flip _rightsSet)+  where+    _rightsGet :: [Either a b] -> [b]+    _rightsGet = rights++    _rightsSet :: [c] -> [Either a b] -> [Either a c]+    _rightsSet cs = sndMapAccumL f cs+      where+        f cs     (Left a)  = (cs, Left a)+        f (c:cs) (Right b) = (cs, Right c)+        f []     (Right _) = error "No more cs"++    sndMapAccumL f z = snd . List.mapAccumL f z++firsts :: ([a] -> [b]) -> [(a,c)] -> [(b,c)]+firsts f = uncurry zip . first f . unzipR++mkTrack :: [(Time, a)] -> Track a+mkTrack = view track . map (view delayed)++withDurationR :: (Functor f, HasDuration a) => f a -> f (Duration, a)+withDurationR = fmap $ \x -> (_duration x, x)++-- TODO generalize and move+mapWithDuration :: HasDuration a => (Duration -> a -> b) -> a -> b+mapWithDuration = over dual withDurationL . uncurry+  where+    withDurationL :: (Contravariant f, HasDuration a) => f (Duration, a) -> f a+    withDurationL = contramap $ \x -> (_duration x, x)++    dual :: Iso (a -> b) (c -> d) (Op b a) (Op d c)+    dual = iso Op getOp++dursToVoice :: [Duration] -> Voice ()+dursToVoice = mconcat . map (\d -> stretch d $ return ())++{-+>>> print $ view (mVoiceTVoice) $ (fmap Just (dursToVoice [1,2,1]) <> return Nothing <> return (Just ()))+++-}  -- | -- Group contigous sequences matching/not-matching the predicate.
src/Music/Score/Pitch.hs view
@@ -35,31 +35,27 @@  module Music.Score.Pitch (         -        -- * Pitch type functions+        -- * Pitch type         Pitch,         SetPitch,         Interval,         -        -- * Accessing pitch-        HasPitches(..),+        -- * HasPitch classes         HasPitch(..),+        HasPitches(..),+        fromPitch',+         -- ** Simple versions-        HasPitches',         HasPitch',+        HasPitches',         pitch',         pitches',         -        -- * Converting pitch to container-        fromPitch',-        -        -- * Manipulating pitch-        Transposable,+        -- * Transposition         up,         down,         above,         below,-        inv,-        invertPitches,         octavesUp,         octavesDown,         octavesAbove,@@ -68,23 +64,30 @@         fifthsDown,         fifthsAbove,         fifthsBelow,-        -- ** Utility         _15va,         _8va,         _8vb,         _15vb, -        -- * Inspecting pitch-        highestPitch,-        lowestPitch,+        -- * Inversion+        inv,+        invertPitches,++        -- * Folds+        highest,+        lowest,         meanPitch, -        -- * Intervals-        augmentIntervals,+        -- -- * Intervals+        -- augmentIntervals,          -- TODO pitchIs, to write filter pitchIs ... etc         -- TODO gliss etc +        PitchPair,+        AffinePair,+        Transposable,+           ) where  import           Control.Applicative@@ -109,64 +112,59 @@ import           Music.Score.Slide import           Music.Score.Text import           Music.Score.Ties-import           Music.Score.Tremolo+-- import           Music.Score.Tremolo import           Music.Score.Phrases import           Music.Time import           Music.Time.Internal.Transform  -- |--- This type fuction is used to retrive the /pitch type/ for a given concrete type.------ For types representing pitch, it is generally 'Identity', i.e------ @--- Pitch Integer ~ Integer--- Pitch Double ~ Double--- @------ and so on.+-- This type fuction is used to access the pitch type for a given type. ----- For containers, 'Pitch' provides a morphism:+type family Pitch (s :: *) :: * -- -- @ -- 'Pitch' (c,a)             ~ 'Pitch' a -- 'Pitch' [a]               ~ 'Pitch' a -- 'Pitch' ('Note' a)          ~ 'Pitch' a--- 'Pitch' ('Delayed' a)       ~ 'Pitch' a--- 'Pitch' ('Stretched' a)     ~ 'Pitch' a -- 'Pitch' ('Voice' a)         ~ 'Pitch' a--- 'Pitch' ('Chord' a)         ~ 'Pitch' a--- 'Pitch' ('Track' a)         ~ 'Pitch' a -- 'Pitch' ('Score' a)         ~ 'Pitch' a -- @ ---type family Pitch (s :: *) :: *---- |--- This type fuction is used to retrive the /pitch type/ for a given concrete type.------ For types representing pitch, it is generally 'Constant', i.e+-- For types representing pitch, it is generally 'Identity', i.e -- -- @--- SetPitch a Double ~ a--- SetPitch a Integer ~ a+-- Pitch Integer ~ Integer+-- Pitch Double ~ Double -- @ --+-- and so on.+-- -- For containers, 'Pitch' provides a morphism: --++-- |+-- This type fuction is used to update the pitch type for a given type.+-- The first argument is the new type.+--+type family SetPitch (b :: *) (s :: *) :: *+-- -- @ -- 'SetPitch' b (c,a)          ~ (c, 'SetPitch' b a) -- 'SetPitch' b [a]            ~ ['SetPitch' b a] -- 'SetPitch' g ('Note' a)       ~ Note ('SetPitch' g a)--- 'SetPitch' g ('Delayed' a)    ~ Delayed ('SetPitch' g a)--- 'SetPitch' g ('Stretched' a)  ~ Stretched ('SetPitch' g a) -- 'SetPitch' g ('Voice' a)      ~ 'Voice' ('SetPitch' g a)--- 'SetPitch' g ('Chord' a)      ~ 'Chord' ('SetPitch' g a)--- 'SetPitch' g ('Track' a)      ~ 'Track' ('SetPitch' g a) -- 'SetPitch' g ('Score' a)      ~ 'Score' ('SetPitch' g a) -- @ ---type family SetPitch (b :: *) (s :: *) :: *+-- For types representing pitch, it is generally 'Constant', i.e+--+-- @+-- SetPitch a Double ~ a+-- SetPitch a Integer ~ a+-- @+--+-- For containers, 'SetPitch' provides a morphism:+--  -- | -- Class of types that provide a single pitch.@@ -179,20 +177,18 @@   --   for example:   --   --   @-  --   'view' 'pitch' :: HasPitch a a-  --   @-  ---  --   @-  --   'over' 'pitch'         :: HasPitch' a => a -> Pitch a-  --   'pitch' %~ 'succ'      :: HasPitch' a => a -> a-  --   'pitch' +~ 2         :: (HasPitch' a, Num (Pitch a)) => a -> a-  --   'pitch' .~ c         :: (HasPitch' a, IsPitch a) => a -> a+  --   'pitch' .~ c    :: ('HasPitch'' a, 'IsPitch' a)      => a -> a+  --   'pitch' +~ 2    :: ('HasPitch'' a, 'Num' ('Pitch' a))  => a -> a+  --   'pitch' %~ 'succ' :: ('HasPitch'' a, 'Enum' ('Pitch' a)) => a -> a+  --   'view' 'pitch'    :: 'HasPitches'' a                 => a -> 'Pitch' a+  --   'set'  'pitch'    :: 'HasPitches' a b                => 'Pitch' b -> a -> b+  --   'over' 'pitch'    :: 'HasPitches' a b                => ('Pitch' a -> 'Pitch' b) -> a -> b   --   @   --   pitch :: Lens s t (Pitch s) (Pitch t)  -- |--- Class of types that provide a pitch traversal.+-- Class of types that provide zero or more pitches. -- class (Transformable (Pitch s),        Transformable (Pitch t),@@ -204,15 +200,11 @@   --   for example:   --   --   @-  --   'lengthOf' 'pitches' :: HasPitches a a => a -> Int-  --   @-  ---  --   @-  --   'toListOf' 'pitches' :: HasPitches' a => a -> Pitch a-  --   @-  ---  --   @-  --   'over' 'pitches' :: HasPitches a b => a -> b+  --   'toListOf' 'pitches'  :: 'HasPitches'' a                  => a -> ['Pitch' a]+  --   'allOf' 'pitches'     :: ('HasPitches'' a)                => ('Pitch' a -> 'Bool') -> a -> 'Bool'+  --   'maximumOf' 'pitches' :: ('HasPitches'' a, 'Ord' ('Pitch' a)) => a -> 'Maybe' ('Pitch' a)+  --   'set'  'pitches'      :: 'HasPitches' a b                 => 'Pitch' b -> a -> b+  --   'over' 'pitches'      :: 'HasPitches' a b                 => ('Pitch' a -> 'Pitch' b) -> a -> b   --   @   --   pitches :: Traversal s t (Pitch s) (Pitch t)@@ -222,25 +214,31 @@ type HasPitches' a = HasPitches a a  --- |--- Pitch type.+-- | +-- Access the pitch. --+-- Same as 'pitch', but without polymorphic update.+-- pitch' :: (HasPitch s t, s ~ t) => Lens' s (Pitch s) pitch' = pitch {-# INLINE pitch' #-} --- |--- Pitch type.+-- | +-- Access all pitches.+-- +-- Same as 'pitches', but without polymorphic update. -- pitches' :: (HasPitches s t, s ~ t) => Traversal' s (Pitch s) pitches' = pitches {-# INLINE pitches' #-} ---- TODO flip name of this and Literal.fromPitch (or call that fromPitchL)+-- |+-- Inject a pitch into some larger type.+-- fromPitch' :: (HasPitches' a, IsPitch a) => Pitch a -> a fromPitch' x = c & pitches' .~ x {-# INLINE fromPitch' #-}+-- TODO swap name of this and Music.Pitch.Literal.fromPitch (or call that something else, i.e. fromPitchL)   #define PRIM_PITCH_INSTANCE(TYPE)       \@@ -357,8 +355,7 @@  type instance Pitch (Couple c a)        = Pitch a type instance SetPitch g (Couple c a)   = Couple c (SetPitch g a)-type instance Pitch (TremoloT a)        = Pitch a-type instance SetPitch g (TremoloT a)   = TremoloT (SetPitch g a)+ type instance Pitch (TextT a)           = Pitch a type instance SetPitch g (TextT a)      = TextT (SetPitch g a) type instance Pitch (HarmonicT a)       = Pitch a@@ -372,12 +369,7 @@   pitches = _Wrapped . pitches instance (HasPitch a b) => HasPitch (Couple c a) (Couple c b) where   pitch = _Wrapped . pitch--instance (HasPitches a b) => HasPitches (TremoloT a) (TremoloT b) where-  pitches = _Wrapped . pitches-instance (HasPitch a b) => HasPitch (TremoloT a) (TremoloT b) where-  pitch = _Wrapped . pitch-+   instance (HasPitches a b) => HasPitches (TextT a) (TextT b) where   pitches = _Wrapped . pitches instance (HasPitch a b) => HasPitch (TextT a) (TextT b) where@@ -404,38 +396,70 @@ -- type Interval a = Diff (Pitch a) +type PitchPair  v w = (Num (Scalar v), IsInterval v, IsPitch w)+type AffinePair v w = (VectorSpace v, AffineSpace w)+ -- | -- Class of types that can be transposed, inverted and so on. ---type Transposable a-  = (HasPitches a a,-     VectorSpace (Interval a), AffineSpace (Pitch a),-     IsInterval (Interval a), IsPitch (Pitch a),-     Num (Scalar (Interval a)))+type Transposable a = (+  HasPitches' a,+  AffinePair (Interval a) (Pitch a),+  PitchPair (Interval a) (Pitch a)+  )  -- |--- Transpose up.+-- Transpose pitch upwards. --+-- Not to be confused with matrix transposition.+--+-- >>> up m3 c+-- eb+--+-- >>> up _P5 [c,d,e :: Pitch]+-- [g,a,b]+--+-- >>> up _P5 [440 :: Hertz, 442, 810]+-- [g,a,b]+-- up :: Transposable a => Interval a -> a -> a up v = pitches %~ (.+^ v)+{-# INLINE up #-}  -- |--- Transpose down.+-- Transpose pitch downwards. --+-- Not to be confused with matrix transposition.+--+-- >>> down m3 c+-- a+--+-- >>> down _P5 [c,d,e]+-- [f_,g_,a_]+-- down :: Transposable a => Interval a -> a -> a down v = pitches %~ (.-^ v)+{-# INLINE down #-}  -- | -- Add the given interval above. --+-- >>> above _P8 [c]+-- [c,c']+-- above :: (Semigroup a, Transposable a) => Interval a -> a -> a above v x = x <> up v x+{-# INLINE above #-}  -- | -- Add the given interval below. --+-- >>> below _P8 [c]+-- [c,c_]+-- below :: (Semigroup a, Transposable a) => Interval a -> a -> a below v x = x <> down v x+{-# INLINE below #-}  inv :: Transposable a => Pitch a -> a -> a inv = invertPitches@@ -450,80 +474,109 @@ -- | -- Transpose up by the given number of octaves. --+-- >>> octavesUp 2 c+-- c''+--+-- >>> octavesUp 1 [c,d,e]+-- [c',d',e']+--+-- >>> octavesUp (-1) [c,d,e]+-- [c_,d_,e_]+-- octavesUp :: Transposable a => Scalar (Interval a) -> a -> a octavesUp n = up (_P8^*n)+{-# INLINE octavesUp #-}  -- | -- Transpose down by the given number of octaves. --+-- >>> octavesDown 2 c+-- c__+--+-- >>> octavesDown 1 [c,d,e]+-- [c_,d_,e_]+--+-- >>> octavesDown (-1) [c,d,e]+-- [c',d',e']+-- octavesDown :: Transposable a => Scalar (Interval a) -> a -> a octavesDown n = down (_P8^*n)+{-# INLINE octavesDown #-}  -- | -- Add the given octave above. -- octavesAbove :: (Semigroup a, Transposable a) => Scalar (Interval a) -> a -> a octavesAbove n = above (_P8^*n)+{-# INLINE octavesAbove #-}  -- | -- Add the given octave below. -- octavesBelow :: (Semigroup a, Transposable a) => Scalar (Interval a) -> a -> a octavesBelow n = below (_P8^*n)+{-# INLINE octavesBelow #-}  -- | -- Transpose up by the given number of fifths. -- fifthsUp :: Transposable a => Scalar (Interval a) -> a -> a fifthsUp n = up (_P8^*n)+{-# INLINE fifthsUp #-}  -- | -- Transpose down by the given number of fifths. -- fifthsDown :: Transposable a => Scalar (Interval a) -> a -> a fifthsDown n = down (_P8^*n)+{-# INLINE fifthsDown #-}  -- | -- Add the given octave above. -- fifthsAbove :: (Semigroup a, Transposable a) => Scalar (Interval a) -> a -> a fifthsAbove n = above (_P8^*n)+{-# INLINE fifthsAbove #-}  -- | -- Add the given octave below. -- fifthsBelow :: (Semigroup a, Transposable a) => Scalar (Interval a) -> a -> a fifthsBelow n = below (_P8^*n)+{-# INLINE fifthsBelow #-}  -- | Shorthand for @'octavesUp' 2@. _15va :: Transposable a => a -> a _15va = octavesUp 2+{-# INLINE _15va #-}  -- | Shorthand for @'octavesUp' 1@. _8va :: Transposable a => a -> a _8va  = octavesUp 1+{-# INLINE _8va #-}  -- | Shorthand for @'octavesDown' 1@. _8vb :: Transposable a => a -> a _8vb  = octavesDown 1+{-# INLINE _8vb #-}  -- | Shorthand for @'octavesDown' 2@. _15vb :: Transposable a => a -> a _15vb = octavesDown 2-+{-# INLINE _15vb #-}   -- | -- Return the highest pitch in the given music. ---highestPitch :: (HasPitches' a, Ord (Pitch a)) => a -> Pitch a-highestPitch = maximum . toListOf pitches'+highest :: (HasPitches' a, Ord (Pitch a)) => a -> Maybe (Pitch a)+highest = maximumOf pitches'  -- | -- Return the lowest pitch in the given music. ---lowestPitch :: (HasPitches' a, Ord (Pitch a)) => a -> Pitch a-lowestPitch = maximum . toListOf pitches'+lowest :: (HasPitches' a, Ord (Pitch a)) => a -> Maybe (Pitch a)+lowest = minimumOf pitches'  -- | -- Return the mean pitch in the given music.
src/Music/Score/Slide.hs view
@@ -25,8 +25,6 @@ -- Provides a representation of musical /slides/, commonly known as /glissando/ or -- /portamento/.  ----- /Warning/ This module is experimental.--- -------------------------------------------------------------------------------------  module Music.Score.Slide (@@ -40,7 +38,6 @@ import           Control.Applicative import           Control.Comonad import           Control.Lens            hiding (transform)-import           Control.Lens.Cons.Middle import           Data.Foldable import           Data.Foldable import           Data.Functor.Couple@@ -104,7 +101,6 @@ newtype SlideT a = SlideT { getSlideT :: Couple ((Any, Any), (Any, Any)) a }   deriving (Eq, Show, Ord, Functor, Foldable, Typeable, Applicative, Monad, Comonad) --- | Unsafe: Do not use 'Wrapped' instances instance Wrapped (SlideT a) where   type Unwrapped (SlideT a) = Couple ((Any, Any), (Any, Any)) a   _Wrapped' = iso getSlideT SlideT@@ -138,7 +134,7 @@ slide :: (HasPhrases' s a, HasSlide a) => s -> s slide = mapPhraseWise3 (setBeginSlide True) (setBeginSlide True . setEndSlide True) (setEndSlide True)   where-    mapPhraseWise3 f g h = over phrases' (over _head f . over _middle g . over _last h)+    mapPhraseWise3 f g h = over phrases' (over _head f . over (_tail . _init) g . over _last h)  -- | -- Add a glissando between the first and the last note.@@ -146,4 +142,4 @@ glissando :: (HasPhrases' s a, HasSlide a) => s -> s glissando = mapPhraseWise3 (setBeginGliss True) (setBeginGliss True . setEndGliss True) (setEndGliss True)   where-    mapPhraseWise3 f g h = over phrases' (over _head f . over _middle g . over _last h)+    mapPhraseWise3 f g h = over phrases' (over _head f . over (_tail . _init) g . over _last h)
src/Music/Score/Text.hs view
@@ -28,12 +28,11 @@   module Music.Score.Text (-         -- * Text         HasText(..),         TextT(..),         text,-+        textLast,   ) where  import           Control.Applicative@@ -84,7 +83,6 @@ instance HasText a => HasText (Score a) where   addText s = fmap (addText s) --- | Unsafe: Do not use 'Wrapped' instances instance Wrapped (TextT a) where   type Unwrapped (TextT a) = Couple [String] a   _Wrapped' = iso getTextT TextT@@ -104,9 +102,17 @@ deriving instance (Real a, Enum a, Integral a) => Integral (TextT a)  -- |--- Attach the given text to the first note in the score.+-- Attach the given text to the first note. -- text :: (HasPhrases' s a, HasText a) => String -> s -> s-text s = over (phrases'._head) (addText s)+text s = over (phrases' . _head) (addText s)++-- |+-- Attach the given text to the last note.+--+textLast :: (HasPhrases' s a, HasText a) => String -> s -> s+textLast s = over (phrases' . _last) (addText s)++  
src/Music/Score/Ties.hs view
@@ -53,6 +53,7 @@ import           Data.Ratio import           Data.Semigroup import           Data.Typeable+import           Data.Monoid.Average import           Data.VectorSpace        hiding (Sum)  import           Music.Dynamics.Literal@@ -96,7 +97,6 @@ newtype TieT a = TieT { getTieT :: ((Any, Any), a) }   deriving (Eq, Ord, Show, Functor, Foldable, Typeable, Applicative, Monad, Comonad) --- | Unsafe: Do not use 'Wrapped' instances instance Wrapped (TieT a) where   type Unwrapped (TieT a) = ((Any, Any), a)   _Wrapped' = iso getTieT TieT@@ -129,6 +129,9 @@   toTied = unzipR . fmap toTied  instance Tiable a => Tiable (Maybe a) where+  toTied = unzipR . fmap toTied++instance Tiable a => Tiable (Average a) where   toTied = unzipR . fmap toTied  instance Tiable a => Tiable (Sum a) where
src/Music/Score/Tremolo.hs view
@@ -28,12 +28,13 @@   module Music.Score.Tremolo (-         -- * Tremolo         HasTremolo(..),-        TremoloT(..),         tremolo, +        -- ** Tremolo note transformer+        TremoloT,+        runTremoloT,   ) where  import           Control.Applicative@@ -46,6 +47,7 @@ import           Data.Semigroup import           Data.Typeable import           Data.Word+import           Data.Functor.Adjunction  (unzipR)  import           Music.Dynamics.Literal import           Music.Pitch.Alterable@@ -53,6 +55,20 @@ import           Music.Pitch.Literal import           Music.Score.Part import           Music.Score.Phrases+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.Time  class HasTremolo a where@@ -70,8 +86,27 @@ instance HasTremolo a => HasTremolo (Score a) where   setTrem n = fmap (setTrem n) +-- |+-- Set the number of tremolo divisions for all notes in the score.+--+tremolo :: HasTremolo a => Int -> a -> a+tremolo = setTrem  +++-- TODO these must be moved upwards+deriving instance (Monoid b, IsPitch a) => IsPitch (Couple b a)+deriving instance (Monoid b, IsDynamics a) => IsDynamics (Couple b a)+deriving instance (Monoid b, Transformable a) => Transformable (Couple b a)+deriving instance (Monoid b, Reversible a) => Reversible (Couple b a)+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+  toTied = unzipR . fmap toTied+++ newtype TremoloT a = TremoloT { getTremoloT :: Couple (Max Word) a }     deriving (Eq, Show, Ord, Functor, Foldable, Typeable, Applicative, Monad, Comonad) --@@ -79,7 +114,6 @@ -- Preferably we would use Natural but unfortunately this is not an instance of Bounded -- --- | Unsafe: Do not use 'Wrapped' instances instance Wrapped (TremoloT a) where   type Unwrapped (TremoloT a) = Couple (Max Word) a   _Wrapped' = iso getTremoloT TremoloT@@ -98,9 +132,44 @@ deriving instance (Num a, Ord a, Real a) => Real (TremoloT a) deriving instance (Real a, Enum a, Integral a) => Integral (TremoloT a) +deriving instance IsPitch a => IsPitch (TremoloT a)+deriving instance IsDynamics a => IsDynamics (TremoloT a)+deriving instance Semigroup a => Semigroup (TremoloT a)+deriving instance Tiable a => Tiable (TremoloT a)++deriving instance HasHarmonic a => HasHarmonic (TremoloT a)+deriving instance HasSlide a => HasSlide (TremoloT a)+deriving instance HasText a => HasText (TremoloT a)+deriving instance Transformable a => Transformable (TremoloT a)+deriving instance Reversible a => Reversible (TremoloT a)+deriving instance Alterable a => Alterable (TremoloT a)+deriving instance Augmentable a => Augmentable (TremoloT a)++type instance Pitch (TremoloT a)              = Pitch a+type instance SetPitch g (TremoloT a)         = TremoloT (SetPitch g a)+type instance Dynamic (TremoloT a)            = Dynamic a+type instance SetDynamic g (TremoloT a)       = TremoloT (SetDynamic g a)+type instance Articulation (TremoloT a)       = Articulation a+type instance SetArticulation g (TremoloT a)  = TremoloT (SetArticulation g a)++instance (HasPitches a b) => HasPitches (TremoloT a) (TremoloT b) where+  pitches = _Wrapped . pitches+instance (HasPitch a b) => HasPitch (TremoloT a) (TremoloT b) where+  pitch = _Wrapped . pitch++instance (HasDynamics a b) => HasDynamics (TremoloT a) (TremoloT b) where+  dynamics = _Wrapped . dynamics+instance (HasDynamic a b) => HasDynamic (TremoloT a) (TremoloT b) where+  dynamic = _Wrapped . dynamic++instance (HasArticulations a b) => HasArticulations (TremoloT a) (TremoloT b) where+  articulations = _Wrapped . articulations+instance (HasArticulation a b) => HasArticulation (TremoloT a) (TremoloT b) where+  articulation = _Wrapped . articulation+ -- |--- Set the number of tremolo divisions for all notes in the score.+-- Get the number of tremolo divisions. ---tremolo :: HasTremolo a => Int -> a -> a-tremolo = setTrem+runTremoloT :: TremoloT a -> (Int, a)+runTremoloT (TremoloT (Couple (Max n, a))) = (fromIntegral n, a) 
src/Music/Time.hs view
@@ -9,8 +9,6 @@ -- Stability   : experimental -- Portability : non-portable (TF,GNTD) ----- Provides generic functions for manipulating time-based structures.--- -------------------------------------------------------------------------------------  module Music.Time (@@ -38,7 +36,6 @@     module Music.Time.Past,     module Music.Time.Nominal,     module Music.Time.Graces,-    module Music.Time.Note,     module Music.Time.Voice,     module Music.Time.Chord,     module Music.Time.Track,@@ -76,3 +73,4 @@ import           Music.Time.Stretched import           Music.Time.Track import           Music.Time.Voice+
src/Music/Time/Behavior.hs view
@@ -24,8 +24,6 @@ -- Stability   : experimental -- Portability : non-portable (TF,GNTD) ----- Behaviors, or time-varying values.--- -------------------------------------------------------------------------------------  module Music.Time.Behavior (@@ -69,6 +67,7 @@ import           Data.Set                      (Set) import qualified Data.Set                      as Set import           Data.VectorSpace+import           Data.String import           Prelude  import           Control.Applicative@@ -175,6 +174,9 @@ -- #ifdef INCLUDE_LIFTED deriving instance AdditiveGroup a => AdditiveGroup (Behavior a) +instance IsString a => IsString (Behavior a) where+  fromString = pure . fromString+ instance IsPitch a => IsPitch (Behavior a) where   fromPitch = pure . fromPitch @@ -337,7 +339,7 @@ -- This can be used to modify a behavior in a specific range, as in -- -- @--- 'line' & 'focusing' ``on`` (2 '<->' 3) '+a~' 1+-- 'line' & 'focusing' `on` (2 '<->' 3) '+a~' 1 -- 'line' & 'focusingOn' (2 '<->' 3) '+~' 1 -- @ --@@ -347,7 +349,7 @@ -}  -- focusing `on` s == focusingOn s-f `on` s = flip whilstM (negateV s) . f+f `on` s = transformed (negateV s) . f  -- | -- Instantly switch from one behavior to another.
src/Music/Time/Bound.hs view
@@ -24,8 +24,6 @@ -- Stability   : experimental -- Portability : non-portable (TF,GNTD) ----- /Warning/ This module is experimental.--- -------------------------------------------------------------------------------------  module Music.Time.Bound (@@ -103,7 +101,6 @@ -- set (namely [(t, t)^.from range | t <- {Time} ]). -- --- | Unsafe: Do not use 'Wrapped' instances instance Wrapped (Bound a) where   type Unwrapped (Bound a) = (Span, a)   _Wrapped' = iso getBound Bound
src/Music/Time/Chord.hs view
@@ -26,8 +26,6 @@ -- Stability   : experimental -- Portability : non-portable (TF,GNTD) ----- /Warning/ This module is experimental.--- -------------------------------------------------------------------------------------  module Music.Time.Chord (@@ -37,9 +35,10 @@        -- * Construction       chord,+      unchord,       unsafeChord, -      -- invertC,+      -- invertChord,       -- inversions,       -- chordToScore,       -- arpUp3,@@ -64,6 +63,7 @@ import           Data.Set               (Set) import qualified Data.Set               as Set import           Data.VectorSpace+import           Data.String  import           Music.Time.Delayed import           Music.Time.Reverse@@ -113,7 +113,6 @@   return = view _Unwrapped . return . return   xs >>= f = view _Unwrapped $ (view _Wrapped . f) `mbind` view _Wrapped xs --- | Unsafe: Do not use 'Wrapped' instances instance Wrapped (Chord a) where   type Unwrapped (Chord a) = (ChordList (ChordEv a))   _Wrapped' = iso getChord Chord@@ -136,12 +135,18 @@ -- instance HasMeta (Chord a) where   -- meta = error "Not implemented: meta" -chord :: Lens (Chord a) (Chord b) [Delayed a] [Delayed b]-chord = _Wrapped+chord :: Getter [Delayed a] (Chord a)+chord = from unsafeChord +unchord :: Lens (Chord a) (Chord b) [Delayed a] [Delayed b]+unchord = _Wrapped+ -- TODO names are not consistent with other types unsafeChord :: Iso (Chord a) (Chord b) [Delayed a] [Delayed b] unsafeChord = _Wrapped++instance IsString a => IsString (Chord a) where+  fromString = pure . fromString  deriving instance IsPitch a => IsPitch (Chord a)	  deriving instance IsInterval a => IsInterval (Chord a)	 
src/Music/Time/Delayed.hs view
@@ -30,14 +30,12 @@ -------------------------------------------------------------------------------------  module Music.Time.Delayed (-      -- * Delayed type-      Delayed,--      -- * Construction-      delayed,+        -- * Delayed type+        Delayed, -      -- ** Inspecting delayed values-      delayedValue,+        -- * Construction+        delayed,+        delayedValue,   ) where  import           Data.AffineSpace@@ -50,9 +48,8 @@ import           Data.Set               (Set) import qualified Data.Set               as Set import           Data.VectorSpace--import           Music.Time.Reverse-import           Music.Time.Split+import           Data.String+import           Data.Functor.Adjunction  (unzipR)  import           Control.Applicative import           Control.Comonad@@ -67,6 +64,8 @@  import           Music.Dynamics.Literal import           Music.Pitch.Literal+import           Music.Time.Reverse+import           Music.Time.Split   -- |@@ -90,9 +89,9 @@ -- @ -- -deriving instance Show a => Show (Delayed a)+instance (Show a, Transformable a) => Show (Delayed a) where+  show x = show (x^.from delayed) ++ "^.delayed" --- | Unsafe: Do not use 'Wrapped' instances instance Wrapped (Delayed a) where   type Unwrapped (Delayed a) = (Time, a)   _Wrapped' = iso _delayedValue Delayed@@ -112,8 +111,23 @@   rev = revDefault  instance Splittable a => Splittable (Delayed a) where-  -- FIXME+  -- 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. --@@ -136,9 +150,7 @@  runDelayed :: Transformable a => Delayed a -> a runDelayed = uncurry delayTime . view _Wrapped-+  where+    delayTime t = delay (t .-. 0) -deriving instance IsPitch a => IsPitch (Delayed a)	 -deriving instance IsInterval a => IsInterval (Delayed a)	 -deriving instance IsDynamics a => IsDynamics (Delayed a) 
src/Music/Time/Future.hs view
@@ -1,3 +1,6 @@ -module Music.Time.Future where+module Music.Time.Future (+    module Music.Time.Past+) where +import Music.Time.Past
src/Music/Time/Graces.hs view
@@ -1,2 +1,59 @@ +{-# LANGUAGE ConstraintKinds            #-}+{-# LANGUAGE DeriveDataTypeable         #-}+{-# LANGUAGE DeriveFoldable             #-}+{-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE DeriveTraversable          #-}+{-# LANGUAGE FlexibleContexts           #-}+{-# LANGUAGE FlexibleInstances          #-}+{-# LANGUAGE GADTs                      #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE MultiParamTypeClasses      #-}+{-# LANGUAGE ScopedTypeVariables        #-}+{-# LANGUAGE TypeFamilies               #-}++-------------------------------------------------------------------------------------+-- |+-- Copyright   : (c) Hans Hoglund 2012–2014+--+-- License     : BSD-style+--+-- Maintainer  : hans@hanshoglund.se+-- Stability   : experimental+-- Portability : non-portable (TF,GNTD)+--+-------------------------------------------------------------------------------------+ module Music.Time.Graces where++import           Control.Applicative+import           Control.Monad+import           Control.Monad.Compose+import           Control.Monad.Plus+import           Data.Foldable          (Foldable)+import qualified Data.Foldable          as Foldable+import           Data.Traversable       (Traversable)+import qualified Data.Traversable       as T+import           Data.Typeable++import Music.Time.Split+import Music.Time.Reverse+import Music.Time.Nominal+import Music.Time.Voice++newtype Graces f a = Graces { getGraces :: (Nominal f a, f a, Nominal f a) }+  deriving (Eq, Ord, Read, Show, Functor, Foldable, Traversable)++-- TODO move+instance Alternative f => Alternative (Nominal f) where+  empty = Nominal empty+  Nominal a <|> Nominal b = Nominal (a <|> b)++instance (Applicative f, Alternative f) => Applicative (Graces f) where+  pure x = Graces (empty, pure x, empty)++-- deriving instance Transformable a => Transformable (Graces a) where+-- deriving instance Splittable a => Splittable (Graces a) where+-- deriving instance Reversible a => Reversible (Graces a) where+
+ src/Music/Time/Internal/Convert.hs view
@@ -0,0 +1,175 @@++{-# LANGUAGE ConstraintKinds            #-}+{-# LANGUAGE DeriveDataTypeable         #-}+{-# LANGUAGE DeriveFoldable             #-}+{-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE FlexibleContexts           #-}+{-# LANGUAGE FlexibleInstances          #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE NoMonomorphismRestriction  #-}+{-# LANGUAGE TypeFamilies               #-}+{-# LANGUAGE ViewPatterns               #-}++-------------------------------------------------------------------------------------+-- |+-- Copyright   : (c) Hans Hoglund 2012-2014+--+-- License     : BSD-style+--+-- Maintainer  : hans@hanshoglund.se+-- Stability   : experimental+-- Portability : non-portable (TF,GNTD)+--+-- Provides miscellaneous conversions.+--+-------------------------------------------------------------------------------------++module Music.Time.Internal.Convert (+        voiceToScore,+        voiceToScore',+        scoreToVoice,+        reactiveToVoice',+  ) where++import           Control.Applicative+import           Control.Lens hiding (transform, time)+import           Control.Monad+import           Control.Monad.Plus+import           Data.AffineSpace+import           Data.AffineSpace.Point+import           Data.Foldable          (Foldable (..))+import           Data.Ord+import           Data.Ratio+import           Data.Semigroup+import           Data.String+import           Data.Traversable+import           Data.VectorSpace++import           Music.Time++import qualified Data.Foldable          as Foldable+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)+    where+        times = 0 : filter (\t -> u < t && t < v) (occs r)+        durs  = toRelativeTimeN' v times+{-# DEPRECATED reactiveToVoice' "" #-}++-- |+-- 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)+    where+       throwTime (t,d,x) = (d,x)+       addRests = concat . snd . mapAccumL g 0+           where+               g u (t, d, x)+                   | u == t    = (t .+^ d, [(t, d, Just x)])+                   | u <  t    = (t .+^ d, [(u, t .-. u, Nothing), (t, d, Just x)])+                   | 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)+-}+++-- 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
@@ -16,13 +16,7 @@ -- Stability   : experimental -- Portability : non-portable (TF,GNTD) ----- Provides rhythmical quantization.------ You generally need not worry about this module, as quantization is handled--- automatically by 'HasBackendScore' instances.------ /Warning/ This modules is poorly named and will probably be split or moved--- soon.+-- Rhythmical quantization. -- ------------------------------------------------------------------------------------- @@ -309,14 +303,14 @@ -- beat = do --     RhythmContext tm ts _ <- getState --     (\d -> (d^/tm) `subDur` ts) <$> match (\d _ ->---         d - ts > 0  &&  isDivisibleBy 2 (d / tm - ts))+--         d - ts > 0  &&  isPowerOf 2 (d / tm - ts))  beat :: Tiable a => RhythmParser a (Rhythm a) beat = do   RhythmContext tm ts _ <- getState   match' $ \d x ->       let d2 = d / tm - ts-      in (d2, x) `assuming` (d - ts > 0 && isDivisibleBy 2 d2)+      in (d2, x) `assuming` (d - ts > 0 && isPowerOf2 d2)   -- | Matches a dotted rhythm@@ -422,17 +416,29 @@ assuming :: a -> Bool -> Maybe a assuming x b = if b then Just x else Nothing ++{-+isDivisibleBy2 :: RealFrac a => a -> Bool+isDivisibleBy2 x = isInt x && even (round x)++isInt :: RealFrac a => a -> Bool+isInt x = x == fromInteger (round x)+-}+ logBaseR :: forall a . (RealFloat a, Floating a) => Rational -> Rational -> a logBaseR k n | isInfinite (fromRational n :: a)      = logBaseR k (n/k) + 1 logBaseR k n | isDenormalized (fromRational n :: a)  = logBaseR k (n*k) - 1 logBaseR k n | otherwise                             = logBase (fromRational k) (fromRational n)  -divides     = isDivisibleBy-divisibleBy = flip isDivisibleBy+-- divides     = isDivisibleBy+-- divisibleBy = flip isDivisibleBy  -- As it sounds, do NOT use infix -- Only works for simple n such as 2 or 3, TODO determine-isDivisibleBy :: Duration -> Duration -> Bool-isDivisibleBy n = (== 0.0) . snd . properFraction . logBaseR (toRational n) . toRational+isPowerOf :: Duration -> Duration -> Bool+isPowerOf n = (== 0.0) . snd . properFraction . logBaseR (toRational n) . toRational++isPowerOf2 :: Duration -> Bool+isPowerOf2 = isPowerOf 2 
src/Music/Time/Internal/Transform.hs view
@@ -30,15 +30,18 @@  module Music.Time.Internal.Transform ( +        module Music.Time.Types,+         -- * The Transformable class         Transformable(..),         itransform,         transformed,+        itransformed,          -- * Apply under a transformation         whilst,-        whilstM,         whilstL,+        whilstL2,         whilstLT,         whilstLD,         whilstStretch,@@ -48,18 +51,18 @@         conjugateS,          -- * Specific transformations-        delay,-        undelay,-        stretch,-        compress,-        -- ** Applied transformations+        -- ** Transformations         delaying,         undelaying,         stretching,         compressing, -        -- ** Utility-        delayTime,    +        -- ** Transforming values+        delay,+        undelay,+        stretch,+        compress,+        delayTime,    ) where @@ -76,8 +79,11 @@ import           Data.Map               (Map) import qualified Data.Map               as Map import           Data.Semigroup+import           Data.Semigroup.Instances () import           Data.Sequence          (Seq) import qualified Data.Sequence          as Seq+import           Data.Set               (Set)+import qualified Data.Set               as Set import           Data.VectorSpace       hiding (Sum (..))  -- |@@ -171,6 +177,9 @@ instance Transformable a => Transformable (Seq a) where   transform t = fmap (transform t) +instance (Ord a, Transformable a) => Transformable (Set a) where+  transform t = Set.map (transform t)+ instance (Ord k, Transformable a) => Transformable (Map k a) where   transform t = Map.map (transform t) @@ -195,20 +204,45 @@ -- | -- 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)+++-- |+-- 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+-- -- @--- 'over' ('transformed' s) = (``whilst`` s)+-- 'stretch' 2 `whilst` 'delaying' 2 -- @ ---transformed :: Transformable a => Span -> Iso' a a-transformed s = iso (transform s) (itransform s)+whilst :: (Transformable a, Transformable b) => (a -> b) -> Span -> a -> b+-- f `whilst` t = transform (negateV t) . f . transform t+f `whilst` t = over (transformed t) f  +delayed :: (Transformable a, Transformable b) => Time -> Iso a b a b+delayed = transformed . delayingTime +stretched :: (Transformable a, Transformable b) => Duration -> Iso a b a b+stretched = transformed . stretching+ -- | -- A transformation that moves a value forward in time. -- delaying :: Duration -> Span delaying x = (0 .+^ x) >-> 1+delayingTime x = x >-> 1  -- | -- A transformation that stretches (augments) a value by the given factor.@@ -261,8 +295,7 @@ -- the value is starting at time zero. -- delayTime :: Transformable a => Time -> a -> a-delayTime t = delay (t .-. 0)-+delayTime = transform . delayingTime   --@@ -287,47 +320,90 @@ -- -- Perhaps we should call the inline version `whilst`, as in @f `whilst` delaying 2@? +{- --- |--- Apply a function under transformation.------ Designed to be used infix, as in------ @--- 'stretch' 2 ``whilst`` 'delaying' 2--- @----whilst :: (Transformable a, Transformable b) => (a -> b) -> Span -> a -> b-f `whilst` t = transform (negateV t) . f . transform t+-- flip whilstM is a lens+flip whilstM :: (Functor f, Transformable a, Transformable b) => (a -> f b) -> Span -> a -> f b+s `flip whilstM` f = fmap (transform (negateV t)) . f . transform t --- |--- Apply a morphism under transformation (monadic version).---+-- is this the same as transformed? -whilstM :: (Functor f, Transformable a, Transformable b) => (a -> f b) -> Span -> a -> f b-f `whilstM` t = fmap (transform (negateV t)) . f . transform t -{---- |--- Apply a morphism under transformation (co-monadic version).----whilstW :: (Functor f, Transformable a, Transformable b) => (f a -> b) -> Span -> f a -> b-f `whilstW` t = transform (negateV t) . f . fmap (transform t)+From lens:+  iso sa bt = dimap sa (fmap bt)+From profunctor:+  dimap ab cd bc = cd . bc . ab+  dimap ab cd    = \f -> cd . f . ab+  ++flip whilstM = transformed+flip whilstM = \s -> iso (transform s) (itransform s)+flip whilstM = \s -> dimap (transform s) (fmap $ itransform s)+flip whilstM = \s f -> (fmap $ itransform s) . f . transform s+flip (\f t -> fmap (transform (negateV t)) . f . transform t) = \s f -> (fmap $ itransform s) . f . transform s++\t f -> fmap (transform (negateV t)) . f . transform t +=+\t f -> (fmap $ itransform t) . f . transform t++\t f -> fmap (itransform t) . f . transform t +=+\t f -> fmap (itransform t) . f . transform t+++++Something similar to whilstL* is being used in Note/Delayed/Stretched+Are they the same?++whilstL l f (s,a)  = (s,) <$> (l $ transformed s f) a+whilstL id f (s,a) = (s,) <$> (transformed s f) a+whilstL id         = \f (s,a) -> (s,) <$> (transformed s f) a++whilstL id+  :: (Transformable a, Transformable b, Functor f) =>+     (a -> f b) -> (Span, a) -> f (Span, b)+ -}++-- dofoo+  -- :: Functor f => (t -> t2) -> (a1 -> a) -> (t2 -> f a1) -> (t1, t) -> f (t1, a)+dofoo v w = \f (s,a) -> (s,) <$> w s <$> f ((v s) a)++++dobar :: (Functor f) ++  => +  (sp -> (s -> f t) -> (s -> f t)) +  -> ((s -> f t) -> a -> f b)+  -> (s -> f t)  -> ((sp, a) -> f (sp, b))++dobar q l = \f (s,a) -> (s,) <$> (l (q s f)) a++-- whilstL2 :: (Transformable a, Transformable b) => Lens (Span, a) (Span, b) a b+whilstL2 = dofoo (transform) (transform . negateV)+ whilstL :: (Functor f, Transformable a, Transformable b)   => LensLike f s t a b   -> LensLike f (Span,s) (Span,t) a b-whilstL  l f (s,a) = (s,) <$> (l $ f `whilstM` s) a+  -- whilstL l = whilstL2 . l+whilstL l = dobar transformed l +{-+If we could rewrite (whilstL l) as (whilstLXX . l)++-}+ whilstLT :: (Functor f, Transformable a, Transformable b)   => LensLike f s t a b   -> LensLike f (Time,s) (Time,t) a b-whilstLT l f (t,a) = (t,) <$> (l $ f `whilstM` (t >-> 1)) a+whilstLT = dobar delayed  whilstLD :: (Functor f, Transformable a, Transformable b)   => LensLike f s t a b   -> LensLike f (Duration,s) (Duration,t) a b-whilstLD l f (d,a) = (d,) <$> (l $ f `whilstM` (0 >-> d)) a+whilstLD = dobar stretched   -- |@@ -352,23 +428,16 @@ -- | -- Transforms a lens of to a 'Transformable' type to act inside a transformation. ---spanned :: (Transformable a, Transformable b) => Span -> Lens a b a b-spanned s = flip whilstM (negateV s)---- |--- Transforms a lens of to a 'Transformable' type to act inside a transformation.--- -- Designed to be used infix, as in -- -- @--- l ``onSpan`` (2 \<-> 3)+-- l `onSpan` (2 \<-> 3) -- @ ---onSpan :: (Transformable a, Functor f) => LensLike' f a b -> Span -> LensLike' f a b+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 -- TODO name --- TODO move!-deriving instance Functor Sum-deriving instance Functor Product-+-- deriving instance Functor Sum+-- deriving instance Functor Product
src/Music/Time/Internal/Util.hs view
@@ -15,7 +15,21 @@ -- ------------------------------------------------------------------------------------- -module Music.Time.Internal.Util where+module Music.Time.Internal.Util (+  showRatio,+  list,+  single,+  inspecting,+  inspectingBy,+  withPrevNext,+  rotate,+  tripped,+  through,+  uncurry3,+  partial,+  partial2,+  partial3,+  ) where  {-     Rules:
src/Music/Time/Juxtapose.hs view
@@ -66,7 +66,7 @@ -- Move a value so that -- -- @--- '_offset' (a ``lead`` b) = '_onset' b+-- '_offset' (a `lead` b) = '_onset' b -- @ -- --@@ -77,7 +77,7 @@ -- Move a value so that -- -- @--- '_offset' a = '_onset' (a ``follow`` b)+-- '_offset' a = '_onset' (a `follow` b) -- @ -- follow :: (HasPosition a, HasPosition b, Transformable b) => a -> b -> b@@ -167,55 +167,3 @@ times :: (Semigroup a, Monoid a, HasPosition a, Transformable a) => Int -> a -> a times n = scat . replicate n -{----- |--- Like '<>', but scaling the second agument to the duration of the first.------ > Score a -> Score a -> Score a----sustain         :: (Semigroup a, Stretchable a, HasDuration a, Fractional d, d ~ Duration) =>-                a -> a -> a---- |--- Like '|>' but with a negative delay on the second element.------ > Duration -> Score a -> Score a -> Score a----anticipate      :: (Semigroup a, Transformable a, HasOnset a, HasOffset a, Ord d, d ~ Duration) =>-                d -> a -> a -> a--x `sustain` y     = x <> duration x `stretchTo` y-anticipate t a b  =  a <> startAt (offset a .-^ t) b---- Like '<>', but truncating the second agument to the duration of the first.--- prolong x y = x <> before (duration x) y---- |--- Repeat once for each element in the list.------ Example:------ > repeated [1,2,1] (c^*)------ Simple type:------ > [a] -> (a -> Score Note) -> Score Note----repeated        :: (Monoid' b, Transformable b, HasOnset b, HasOffset b) =>-                [a] -> (a -> b) -> b---- |--- Repeat a number of times and scale down by the same amount.------ > Duration -> Score a -> Score a----group           :: (Monoid' a, Transformable a, Fractional d, d ~ Duration, HasOnset a, HasOffset a) =>-                Int -> a -> a--times n     = scat . replicate n-repeated    = flip (\f -> scat . fmap f)-group n     = times n . (fromIntegral n `compress`)--}---- JUNK
src/Music/Time/Meta.hs view
@@ -23,16 +23,8 @@ -- Stability   : experimental -- Portability : non-portable (TF,GNTD) ----- Provides a way to annotate data-types with 'Transformable' meta-data. See--- "Music.Score.Meta" for more specific applications.------ Inspired by Clojure and Diagram's styles, in turn based on xmonad's @Message@ type,--- in turn based on ideas in:------ Simon Marlow.--- /An Extensible Dynamically-Typed Hierarchy of Exceptions/.--- Proceedings of the 2006 ACM SIGPLAN workshop on--- Haskell. <http://research.microsoft.com/apps/pubs/default.aspx?id=67968>.+-- Provides a way to annotate data-types with 'Transformable' meta-data.+-- Inspired by Clojure meta-data and Diagrams styles. -- ------------------------------------------------------------------------------------- @@ -59,10 +51,13 @@          -- ** The HasMeta class         HasMeta(..),+        getMeta,+        mapMeta,         setMeta,+        applyMeta,         setMetaAttr,         setMetaTAttr,-        applyMeta,+        preserveMeta,          -- ** Add meta-data to arbitrary types         AddMeta,@@ -199,12 +194,19 @@ instance HasMeta a => HasMeta (Twain b a) where   meta = _Wrapped . meta --- TODO call withMeta a la Clojure?+-- | Extract meta-data.+getMeta :: HasMeta a => a -> Meta+getMeta = view meta++-- | Update meta-data. setMeta :: HasMeta a => Meta -> a -> a-setMeta m = set meta m+setMeta = set meta --- | Apply meta-information by combining it (on the left) with the---   existing meta-information.+-- | Map over meta-data.+mapMeta :: HasMeta a => (Meta -> Meta) -> a -> a+mapMeta = over meta++-- | Apply meta-information by combining it with existing meta-information. applyMeta :: HasMeta a => Meta -> a -> a applyMeta m = over meta (<> m) @@ -215,6 +217,10 @@ -- | Update a meta attribute. setMetaTAttr :: (TAttributeClass b, HasMeta a) => b -> a -> a setMetaTAttr a = applyMeta (wrapTMeta a)++-- | Apply a function without affecting meta-data.+preserveMeta :: (HasMeta a, HasMeta b) => (a -> b) -> a -> b+preserveMeta f x = let m = view meta x in set meta m (f x)  -- | -- Annotate an arbitrary type with meta-data, preserving instances of
src/Music/Time/Nominal.hs view
@@ -1,2 +1,58 @@ +{-# LANGUAGE ConstraintKinds            #-}+{-# LANGUAGE DeriveDataTypeable         #-}+{-# LANGUAGE DeriveFoldable             #-}+{-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE DeriveTraversable          #-}+{-# LANGUAGE FlexibleContexts           #-}+{-# LANGUAGE FlexibleInstances          #-}+{-# LANGUAGE GADTs                      #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE MultiParamTypeClasses      #-}+{-# LANGUAGE ScopedTypeVariables        #-}+{-# LANGUAGE TypeFamilies               #-}++-------------------------------------------------------------------------------------+-- |+-- Copyright   : (c) Hans Hoglund 2012–2014+--+-- License     : BSD-style+--+-- Maintainer  : hans@hanshoglund.se+-- Stability   : experimental+-- Portability : non-portable (TF,GNTD)+--+-------------------------------------------------------------------------------------+ module Music.Time.Nominal where++import           Control.Applicative+import           Control.Monad+import           Control.Monad.Compose+import           Control.Monad.Plus+import           Data.Foldable          (Foldable)+import qualified Data.Foldable          as Foldable+import           Data.Traversable       (Traversable)+import qualified Data.Traversable       as T+import           Data.Typeable++import Music.Time.Split+import Music.Time.Reverse++newtype Nominal f a = Nominal { getNominal :: f a }+  deriving (Eq, Ord, Read, Show, Functor, Foldable, Traversable, Monad)++instance Applicative f => Applicative (Nominal f) where+  pure = Nominal . pure+  Nominal f <*> Nominal x = Nominal (f <*> x)++instance Transformable (Nominal f a) where+  transform _ = id++instance Splittable (Nominal f a) where+  split _ x = (x,x)++instance Reversible (f a) => Reversible (Nominal f a) where+  rev (Nominal x) = Nominal (rev x)+
src/Music/Time/Note.hs view
@@ -47,11 +47,9 @@ import           Data.Semigroup import           Data.Set               (Set) import qualified Data.Set               as Set+import           Data.String import           Data.VectorSpace -import           Music.Time.Reverse-import           Music.Time.Split- import           Control.Applicative import           Control.Comonad import           Control.Comonad.Env@@ -62,8 +60,15 @@ import qualified Data.Foldable          as Foldable import           Data.PairMonad import           Data.Typeable++import           Music.Pitch.Literal+import           Music.Dynamics.Literal import           Music.Time.Internal.Util (through, tripped) +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'.@@ -105,7 +110,6 @@ -- instance ComonadEnv Span Note where   -- ask = noteValueSpan --- | Unsafe: Do not use 'Wrapped' instances instance Wrapped (Note a) where   type Unwrapped (Note a) = (Span, a)   _Wrapped' = iso _noteValue Note@@ -124,10 +128,24 @@ 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    (1 - (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++instance IsString a => IsString (Note a) where+  fromString = pure . fromString++instance IsPitch a => IsPitch (Note a) where+  fromPitch = pure . fromPitch++instance IsInterval a => IsInterval (Note a) where+  fromInterval = pure . fromInterval++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).
src/Music/Time/Past.hs view
@@ -1,24 +1,83 @@ +{-# LANGUAGE RankNTypes                 #-}+{-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE ViewPatterns               #-}+{-# LANGUAGE CPP #-}+ module Music.Time.Past where -import Music.Time.Split-import Music.Time.Reverse-import Music.Time.Segment-import Music.Time.Behavior+import Control.Lens -- DEBUG+import           Control.Applicative+import           Control.Comonad+import           Data.Functor.Couple+import           Data.Ord            (comparing)+import           Data.List           (takeWhile, sort, sortBy, group)+import           Data.List.Ordered+import           Data.Maybe+import           Data.Semigroup+import           Control.Monad +import           Music.Time.Behavior+import           Music.Time.Reverse+import           Music.Time.Segment+import           Music.Time.Split+ -- |--- Past represents a value occuring /up to/ some point in time.+-- 'Past' represents a value occuring /before and at/ some point in time. ----- It may be seen as a note whose era is a left-open time interval.+-- It may be seen as a note whose era is a left-open, right-inclusive time interval. ---newtype Past a = Past { getPast :: (a, Time) }+newtype Past a = Past { getPast :: (Min Time, a) }+  deriving (Eq, Ord, Functor) --- | Query a past value.+-- |+-- 'Future' represents a value occuring /at and after/ some point in time.+--+-- 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) }+  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++-- | Query a past value. Semantic function. past :: Past a -> Time -> Maybe a-past (Past (x, t)) t'+past (Past (extract -> t, x)) t'   | 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++-- TODO more elegant+indexPast :: [Past a] -> Time -> Maybe a+indexPast ps t = firstTrue $ fmap (\p -> past p t) $ sortBy (comparing _onset) ps++firstTrue :: [Maybe a] -> Maybe a+firstTrue = listToMaybe . join . fmap maybeToList+-- firstTrue = join . listToMaybe . dropWhile isNothing+ -- | Project a segment (backwards) up to the given point. pastSeg :: Past (Segment a) -> Behavior (Maybe a) pastSeg = undefined++-- | Project a segment starting from the given point.+futureSeg :: Future (Segment a) -> Behavior (Maybe a)+futureSeg = undefined+++
src/Music/Time/Position.hs view
@@ -37,21 +37,22 @@        -- * The HasPosition class       HasPosition(..),-      -- * Inspecting position++      -- * Era       era,++      -- * Position       position, -      -- * Specific positions+      -- ** Specific positions       onset,       midpoint,       offset,       preOnset,       postOffset,--      -- ** Deprecated       postOnset, -      -- * Moving to absolute positions+      -- * Moving       startAt,       stopAt,       placeAt,
src/Music/Time/Reactive.hs view
@@ -29,8 +29,8 @@ module Music.Time.Reactive (         -- * Reactive type         Reactive,-      -        -- * Construction++        -- * Query         initial,         final,         intermediate,@@ -38,19 +38,24 @@         updates,         occs,         atTime,-        splitReactive,++        -- * Construction       -        -- * Combinators+        -- * Combine         switchR,         trimR, -        -- * Sampling and discretization+        -- * Split+        splitReactive,++        -- * Sampling         continous,         continousWith,         sample,         -- TODO         -- window,         -- windowed,   +   ) where  -- Reactive values, or piecewise functions of time.
src/Music/Time/Reverse.hs view
@@ -36,7 +36,7 @@         -- * The Reversible class         Reversible(..), -        -- * Reversed values+        -- * Reversing         reversed,         revDefault, @@ -90,7 +90,7 @@ -- @ -- -- @--- 'rev' s ``transform`` a = 'rev' (s ``transform`` a)+-- 'rev' s `transform` a = 'rev' (s `transform` a) -- @ -- -- or equivalently,@@ -168,6 +168,7 @@ -- revDefault x = (stretch (-1) `whilst` undelaying (_position x 0.5 .-. 0)) x revDefault x = stretch (-1) x + newtype NoReverse a = NoReverse { getNoReverse :: a }   deriving (Typeable, Eq, Ord, Show) @@ -180,8 +181,8 @@ -- | -- View the reverse of a value. ----- >>> [1,2,3] & reversed %~ sort--- > [3,2,1]+-- >>> [1,2,3] & reversed %~ Data.List.sort+-- [3,2,1] -- reversed :: Reversible a => Iso' a a reversed = iso rev rev
src/Music/Time/Score.hs view
@@ -33,22 +33,24 @@         -- * Score type         Score, +        -- * Query+         -- * Construction         score,-      -        -- ** Extracting values         notes,+        eras,         events,-      -        -- ** Pattern matching         singleNote, -        -- ** Unsafe versions-        unsafeNotes,-        unsafeEvents,-+        -- * Traversal+        mapWithSpan,+        filterWithSpan,+        mapFilterWithSpan,+        mapEvents,+        filterEvents,+        mapFilterEvents, -        -- * Simultaneous values+        -- * Simultaneous         -- TODO check for overlapping values etc         simult,         simultaneous,@@ -56,15 +58,11 @@         -- * Normalize         normalizeScore,         printEras,-        -        -- * Traversing-        mapWithSpan,-        filterWithSpan,-        mapFilterWithSpan,-        mapEvents,-        filterEvents,-        mapFilterEvents, +        -- * Unsafe versions+        unsafeNotes,+        unsafeEvents,+           ) where  import           Data.AffineSpace@@ -77,6 +75,7 @@ import           Data.Set               (Set) import qualified Data.Set               as Set import           Data.VectorSpace+import           Data.String import           Data.Functor.Adjunction  (unzipR)  import           Music.Time.Juxtapose   (scat)@@ -168,6 +167,7 @@   mzero = mempty   mplus = mappend +{- instance FunctorWithIndex Span Score where   imap f = over (_Wrapped._2) $ imap f @@ -176,6 +176,7 @@  instance TraversableWithIndex Span Score where   itraverse f (Score (m,x)) = fmap (\x -> Score (m,x)) $ itraverse f x+-}  instance Transformable (Score a) where   transform t (Score (m,x)) = Score (transform t m, transform t x)@@ -189,18 +190,21 @@       (m1, m2) = split t m       (x1, x2) = split t x +-- TODO move these two "implementations" to NScore instance HasPosition (Score a) where-  _onset (Score (_,x))    = _onset x-  _offset (Score (_,x))   = _offset x-  _position (Score (_,x)) = _position x+  _position = _position . snd . view _Wrapped' . normalizeScore'+  -- TODO clean up in terms of AddMeta and optimize  instance HasDuration (Score a) where-  _duration (Score (_,x)) = _duration x+  _duration x = _offset x .-. _onset x    -- Lifted instances +instance IsString a => IsString (Score a) where+  fromString = pure . fromString+ instance IsPitch a => IsPitch (Score a) where   fromPitch = pure . fromPitch @@ -246,7 +250,9 @@ newtype NScore a = NScore { getNScore :: [ScoreNote a] }   deriving ({-Eq, -}{-Ord, -}{-Show, -}Functor, Foldable, Traversable, Semigroup, Monoid, Typeable, Show, Eq) --- | Unsafe: Do not use 'Wrapped' instances+instance (Show a, Transformable a) => Show (Score a) where+  show x = show (x^.notes) ++ "^.score"+ instance Wrapped (NScore a) where   type Unwrapped (NScore a) = [ScoreNote a]   _Wrapped' = iso getNScore NScore@@ -269,6 +275,7 @@   mzero = mempty   mplus = mappend +{- instance FunctorWithIndex Span NScore where   imap = undefined   -- TODO@@ -280,6 +287,7 @@ instance TraversableWithIndex Span NScore where   itraverse = undefined   -- TODO+-}  instance Transformable (NScore a) where   transform t (NScore xs) = NScore (fmap (transform t) xs)@@ -459,6 +467,7 @@ 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) @@ -512,16 +521,38 @@  -- | Mainly useful for backends. normalizeScore :: Score a -> Score a-normalizeScore = reset . absDurations+normalizeScore = reset . normalizeScore'   where     reset x = set onset (view onset x `max` 0) x-    absDurations = over (notes.each.era.delta._2) abs +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++-- |+-- Extract all eras of the given score.+--+-- >>> printEras $ scat [c,d,e :: Score Integer]+-- 0 <-> 1+-- 1 <-> 2+-- 2 <-> 3+-- printEras :: Score a -> IO ()-printEras = mapM_ print . toListOf (notes.each.era)+printEras = mapM_ print . toListOf eras -eras :: Transformable a => Score a -> [Span]-eras = toListOf (notes . each . era)+-- |+-- Print all eras of the given score.+--+-- >>> toListOf eras $ scat [c,d,e :: Score Integer]+-- [0 <-> 1,1 <-> 2,2 <-> 3]+--+eras :: Traversal' (Score a) Span+eras = notes . each . era  chordEvents :: Transformable a => Span -> Score a -> [a] chordEvents s = fmap extract . filter ((== s) . view era) . view notes@@ -534,7 +565,7 @@     -- es :: [Era]     -- evs :: [[a]]     -- vs :: [(Time, Duration, [a])]-    es  = List.nub $ eras sc+    es  = List.nub $ toListOf eras sc     evs = fmap (`chordEvents` sc) es     vs  = zipWith (\(view delta -> (t,d)) a -> (t,d,a)) es evs 
src/Music/Time/Segment.hs view
@@ -37,18 +37,11 @@         -- $musicTimeBehaviorExamples         -- (!^),         -- behavior',-        behavior, -        -- ** Combinators-        switch,-        switch',-        splice,-        trim,-        trimBefore,-        trimAfter,-        concatB,+        -- * Construction+        behavior, -        -- * Common behaviors+        -- ** Common versions         line,         unit,         impulse,@@ -58,21 +51,35 @@         sine,         cosine, +        -- ** Combine+        switch,+        switch',+        splice,+        trim,+        trimBefore,+        trimAfter,+        concatB,+         -- * Segment type         Segment,         -- ** Examples         -- $XXmusicTimeSegmentExamples++        -- * Construction         segment, -        -- ** Combinators+        -- * Combine         focusing,         apSegments',         apSegments,         -- concatS, +        -- * Bound type         Bound,+        -- * Query                 bounds,         bounding,+        -- * Combine         trim,         splice,         bounded',@@ -355,7 +362,7 @@ -- View part of a 'Behavior' as a 'Segment'. -- -- @--- 'line' & 'focusing' ``onSpan`` (2 '<->' 3) '*~' 0+-- 'line' & 'focusing' `onSpan` (2 '<->' 3) '*~' 0 -- @ -- focusing :: Lens' (Behavior a) (Segment a)
src/Music/Time/Split.hs view
@@ -35,8 +35,9 @@          -- * The Splittable class         Splittable(..),++        -- * Miscellaneous         splitAbs,-             chunks,    ) where@@ -72,12 +73,18 @@ -- -- @ -- '_duration' ('beginning' t x) + '_duration' ('ending' t x) = '_duration' x--- '_duration' ('beginning' t x) = t ``min`` '_duration' x                    iff t >= 0--- '_duration' ('ending' t x)    = '_duration' x - (t ``min`` '_duration' x)    iff t >= 0+-- '_duration' ('beginning' t x) = t `min` '_duration' x                    iff t >= 0+-- '_duration' ('ending' t x)    = '_duration' x - (t `min` '_duration' x)    iff t >= 0 -- @ -- -- (Note that any of these three laws can be derived from the other two, so it is -- sufficient to prove two!).+--+-- >>> (\x -> fmap (flip split x) [-2,-1,0,0.5,1,2]) $ (1::Duration)+-- [(0,1),(0,1),(0,1),((1/2),(1/2)),(1,0),(1,0)]+--+-- >>> (\x -> fmap (flip split x) [-2,-1,0,0.5,1,2]) $ (0<->1)+-- [(0 <-> 0,0 <-> 1),(0 <-> 0,0 <-> 1),(0 <-> 0,0 <-> 1),(0 <-> (1/2),(1/2) <-> 1),(0 <-> 1,1 <-> 1),(0 <-> 1,1 <-> 1)] -- class Splittable a where   split      :: Duration -> a -> (a, a)
src/Music/Time/Stretched.hs view
@@ -29,14 +29,12 @@ -------------------------------------------------------------------------------------  module Music.Time.Stretched (--        -- * Stretched values+        -- * Stretched type         Stretched,          -- * Construction         stretched,         stretchedValue,   -   ) where  import           Data.AffineSpace@@ -49,11 +47,9 @@ import           Data.Set               (Set) import qualified Data.Set               as Set import           Data.VectorSpace+import           Data.String import           Data.Functor.Couple -import           Music.Time.Reverse-import           Music.Time.Split- import           Control.Applicative import           Control.Comonad import           Control.Comonad.Env@@ -65,6 +61,12 @@ 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'. --@@ -82,9 +84,6 @@ -- @ -- --- TODO move-deriving instance Traversable (Couple a)- -- >>> stretch 2 $ (5,1)^.stretched -- (10,1)^.stretched --@@ -96,14 +95,12 @@ 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 --- | Unsafe: Do not use 'Wrapped' instances instance Wrapped (Stretched a) where   type Unwrapped (Stretched a) = (Duration, a)   _Wrapped' = iso (getCouple . _stretchedValue) (Stretched . Couple)@@ -123,8 +120,23 @@   beginning d = over _Wrapped $ \(s, v) -> (beginning d s, beginning d v)   ending    d = over _Wrapped $ \(s, v) -> (ending    d s, ending    d v) -deriving instance Show a => Show (Stretched a)+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. --@@ -139,9 +151,6 @@ 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 #-} -runStretched :: Transformable a => Stretched a -> a-runStretched = uncurry stretch . view _Wrapped---- JUNK
src/Music/Time/Track.hs view
@@ -79,7 +79,7 @@ -- newtype Track a = Track { getTrack :: TrackList (TrackEv a) }   deriving (Functor, Foldable, Traversable, Semigroup, Monoid, Typeable, Show, Eq)-{-# DEPRECATED Track "Use 'Chord'" #-}+-- {-# DEPRECATED Track "Use 'Chord'" #-}  -- A track is a list of events with explicit onset. --@@ -113,7 +113,6 @@   return = view _Unwrapped . return . return   xs >>= f = view _Unwrapped $ (view _Wrapped . f) `mbind` view _Wrapped xs --- | Unsafe: Do not use 'Wrapped' instances instance Wrapped (Track a) where   type Unwrapped (Track a) = (TrackList (TrackEv a))   _Wrapped' = iso getTrack Track
src/Music/Time/Transform.hs view
@@ -36,27 +36,23 @@         Transformable(..),         itransform,         transformed,--        -- * Apply under a transformation         whilst,         spanned,         onSpan,-        -- conjugateS,+        conjugateS,          -- * Specific transformations         -- ** Transformations-        delay,-        undelay,-        stretch,-        compress,--        -- ** Transforming values         delaying,         undelaying,         stretching,         compressing, -        -- * Utility+        -- ** Transforming values+        delay,+        undelay,+        stretch,+        compress,         delayTime,    ) where
src/Music/Time/Types.hs view
@@ -86,7 +86,29 @@         isProper,         isBefore,         encloses,+        properlyEncloses,         overlaps,+        +        afterOnset,+        strictlyAfterOnset,+        beforeOnset,+        strictlyBeforeOnset,+        afterOffset,+        strictlyAfterOffset,+        beforeOffset,+        strictlyBeforeOffset,+        +        startsWhenStarts,+        startsWhenStops,+        stopsWhenStops,+        stopsWhenStarts,+        +        startsBefore,+        startsLater,+        stopsAtTheSameTime,+        stopsBefore,+        stopsLater,+                 -- union         -- intersection (alt name 'overlap')         -- difference (would actually become a split)@@ -130,6 +152,7 @@ -- for 'Fractional' and 'RealFrac'. -- type TimeBase = Rational+-- type TimeBase = Fixed E12 {- type TimeBase = Fixed E12 @@ -264,8 +287,8 @@ -- | -- @length (offsetPoints x xs) = length xs + 1@ ----- >>> offsetPoints 0 [1,2,1]--- [0,1,2,1]+-- >>> offsetPoints (0 ::Double) [1,2,1]+-- [0.0,1.0,3.0,4.0] -- -- @ -- offsetPoints :: 'AffineSpace' a => 'Time' -> ['Duration'] -> ['Time']@@ -371,17 +394,17 @@ -- $musicTimeSpanIsos -- -- >>> (2 <-> 3)^.range--- > (2, 3)--- >--- >>> hs> (2 <-> 3)^.delta--- > (2, 1)--- >--- >>> hs> (10 >-> 5)^.range--- > (10, 15)--- >--- >>> hs> (10 >-> 5)^.delta--- > (10, 5)+-- (2,3) --+-- >>> (2 <-> 3)^.delta+-- (2,1)+--+-- >>> (10 >-> 5)^.range+-- (10,15)+--+-- >>> (10 >-> 5)^.delta+-- (10,5)+--  instance Show Span where   -- show = showDelta@@ -422,6 +445,10 @@ -- (b .-^ a) <-> b = a <-< b -- +infixl 6 <->+infixl 6 >->+infixl 6 <-<+ -- | -- @t \<-\> u@ represents the span between @t@ and @u@. --@@ -514,11 +541,8 @@ -- -- A span is either /forward/, /backward/ or /empty/. ----- >>> any id [isForwardSpan x, isBackwardSpan x, isEmptySpan x]--- True------ >>> all not [isForwardSpan x, isBackwardSpan x, isEmptySpan x]--- False+-- @any id [isForwardSpan x, isBackwardSpan x, isEmptySpan x] == True@+-- @all not [isForwardSpan x, isBackwardSpan x, isEmptySpan x] == False@ --  -- |@@ -571,23 +595,161 @@ isProper (view range -> (t, u)) = t < u {-# DEPRECATED isProper "Use 'isForwardSpan'" #-} +infixl 5 `inside`+infixl 5 `encloses`+infixl 5 `properlyEncloses`+infixl 5 `overlaps`+-- infixl 5 `encloses`+-- infixl 5 `encloses`+-- infixl 5 `encloses`+ -- | -- Whether the given point falls inside the given span (inclusively). -- -- Designed to be used infix, for example ----- @--- 0.5 ``inside`` (1 '<->' 2)--- @+-- >>> 0.5 `inside` 1 <-> 2+-- False --+-- >>> 1.5 `inside` 1 <-> 2+-- True+--+-- >>> 1 `inside` 1 <-> 2+-- True+-- inside :: Time -> Span -> Bool inside x (view range -> (t, u)) = t <= x && x <= u  -- | -- Whether the first given span encloses the second span. --+-- >>> 0 <-> 3 `encloses` 1 <-> 2+-- True+--+-- >>> 0 <-> 2 `encloses` 1 <-> 2+-- True+--+-- >>> 1 <-> 3 `encloses` 1 <-> 2+-- True+--+-- >>> 1 <-> 2 `encloses` 1 <-> 2+-- True+-- encloses :: Span -> Span -> Bool a `encloses` b = _onsetS b `inside` a && _offsetS b `inside` a++-- |+-- Whether the first given span encloses the second span.+--+-- >>> 0 <-> 3 `properlyEncloses` 1 <-> 2+-- True+--+-- >>> 0 <-> 2 `properlyEncloses` 1 <-> 2+-- True+--+-- >>> 1 <-> 3 `properlyEncloses` 1 <-> 2+-- True+--+-- >>> 1 <-> 2 `properlyEncloses` 1 <-> 2+-- False+--+properlyEncloses :: Span -> Span -> Bool+a `properlyEncloses` b = a `encloses` b && a /= b++++-- TODO more intuitive param order++afterOnset :: Time -> Span -> Bool+t `afterOnset` s = t >= _onsetS s++strictlyAfterOnset :: Time -> Span -> Bool+t `strictlyAfterOnset` s = t > _onsetS s++beforeOnset :: Time -> Span -> Bool+t `beforeOnset` s = t <= _onsetS s++strictlyBeforeOnset :: Time -> Span -> Bool+t `strictlyBeforeOnset` s = t < _onsetS s++afterOffset :: Time -> Span -> Bool+t `afterOffset` s = t >= _offsetS s++strictlyAfterOffset :: Time -> Span -> Bool+t `strictlyAfterOffset` s = t > _offsetS s++beforeOffset :: Time -> Span -> Bool+t `beforeOffset` s = t <= _offsetS s++strictlyBeforeOffset :: Time -> Span -> Bool+t `strictlyBeforeOffset` s = t < _offsetS s+++-- Param order OK++-- Name?+startsWhenStarts :: Span -> Span -> Bool+a `startsWhenStarts` b = _onsetS a == _onsetS b++-- Name?+startsWhenStops :: Span -> Span -> Bool+a `startsWhenStops` b = _onsetS a == _offsetS b++-- Name?+stopsWhenStops :: Span -> Span -> Bool+a `stopsWhenStops` b = _offsetS a == _offsetS b++-- Name?+stopsWhenStarts :: Span -> Span -> Bool+a `stopsWhenStarts` b = _offsetS a == _onsetS b+++startsBefore :: Span -> Span -> Bool+a `startsBefore` b = _onsetS a < _onsetS b++startsLater :: Span -> Span -> Bool+a `startsLater` b = _onsetS a > _onsetS b++stopsAtTheSameTime :: Span -> Span -> Bool+a `stopsAtTheSameTime` b = _offsetS a == _offsetS b++stopsBefore :: Span -> Span -> Bool+a `stopsBefore` b = _offsetS a < _offsetS b++stopsLater :: Span -> Span -> Bool+a `stopsLater` b = _offsetS a > _offsetS b++{-+contains+curtails+delays+happensDuring+intersects+trisects+isCongruentTo+overlapsAllOf+overlapsOnlyOnsetOf+overlapsOnlyOffsetOf+overlapsOnsetOf+overlapsOffsetOf++++-}++-- timespantools.timespan_2_starts_during_timespan_1+-- timespantools.timespan_2_starts_when_timespan_1_starts+-- timespantools.timespan_2_starts_when_timespan_1_stops+-- timespantools.timespan_2_stops_after_timespan_1_starts+-- timespantools.timespan_2_stops_after_timespan_1_stops+-- timespantools.timespan_2_stops_before_timespan_1_starts+-- timespantools.timespan_2_stops_before_timespan_1_stops+-- timespantools.timespan_2_stops_during_timespan_1+-- timespantools.timespan_2_stops_when_timespan_1_starts+-- timespantools.timespan_2_stops_when_timespan_1_stops+-- timespantools.timespan_2_trisects_timespan_1     ++  -- | -- Whether the given span overlaps.
src/Music/Time/Voice.hs view
@@ -46,12 +46,14 @@         fuse,         fuseBy, -        -- ** Special cases+        -- ** Fuse rests         fuseRests,         coverRests, -        -- * Traversing+        -- * Traversal         -- ** Separating rhythms and values+        valuesV,+        durationsV,         withValues,         withDurations,         rotateValues,@@ -65,6 +67,7 @@         zipVoice3,         zipVoice4,         zipVoiceNoScale,+        -- FIXME compose with (lens assoc unassoc) for the 3 and 4 versions         zipVoiceNoScale3,         zipVoiceNoScale4,         zipVoiceWith,@@ -95,6 +98,9 @@ import           Data.Semigroup import           Data.Set                 (Set) import qualified Data.Set                 as Set+import           Data.Sequence            (Seq)+import qualified Data.Sequence            as Seq+import           Data.String import           Data.VectorSpace  import           Music.Time.Reverse@@ -123,8 +129,11 @@ -- A 'Voice' is a sequential composition of values. Events may not overlap. -- newtype Voice a = Voice { getVoice :: VoiceList (VoiceEv a) }-  deriving (Functor, Foldable, Traversable, Semigroup, Monoid, Typeable, Show, Eq)+  deriving (Functor, Foldable, Traversable, Semigroup, Monoid, Typeable, Eq) +instance (Show a, Transformable a) => Show (Voice a) where+  show x = show (x^.stretcheds) ++ "^.voice"+ -- -- $semantics Voice -- type Voice a = [Stretched a]@@ -146,9 +155,14 @@  -- 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@@ -166,7 +180,6 @@   mzero = mempty   mplus = mappend   --- | Unsafe: Do not use 'Wrapped' instances instance Wrapped (Voice a) where   type Unwrapped (Voice a) = (VoiceList (VoiceEv a))   _Wrapped' = iso getVoice Voice@@ -197,26 +210,15 @@     where       split' = error "TODO" -      -- split' :: Time -> (Duration -> a -> (a,a)) -> [Stretched a] -> ([Stretched a], [Stretched a])-      -- split' t f = over both mcatMaybes . unzipR . snd . Data.List.mapAccumL go (0::Time)-      --   where-      --     go :: Time -> Stretched a -> (Time, (Maybe (Stretched a), Maybe (Stretched a)))-      --     go currentOnset (view (from stretched) -> (d,x))-      --       = let currentOffset = currentOnset .+^ d-      --             theSplit = if t              <= currentOnset           then (Nothing, Just (view stretched (d,x))) else-      --                        if currentOnset   <  t && t < currentOffset then-      --                          let x1 = x-      --                              x2 = x in-      --                          (Just (view stretched (t .-^ currentOnset,x1)), Just (view stretched (d ^-^ (t .-^ currentOnset),x2))) else-      --                        if currentOffset  <= t                      then (Just (view stretched (d,x)), Nothing) else error "Impossible"-      --           in (currentOnset .+^ d, theSplit)- instance Reversible a => Reversible (Voice a) where   rev = over _Wrapped' (fmap rev) -- TODO OK?   -- Lifted instances +instance IsString a => IsString (Voice a) where+  fromString = pure . fromString+ instance IsPitch a => IsPitch (Voice a) where   fromPitch = pure . fromPitch @@ -329,6 +331,7 @@ singleStretched :: Prism' (Voice a) (Stretched a) singleStretched = unsafeStretcheds . single {-# INLINE singleStretched #-}+{-# DEPRECATED singleStretched "Use 'unsafeStretcheds . single'" #-}   -- |@@ -396,7 +399,7 @@ -- Join the given voices without combining durations. -- zipVoiceWithNoScale :: (a -> b -> c) -> Voice a -> Voice b -> Voice c-zipVoiceWithNoScale f a b = zipVoiceWith' (\x y -> x) f a b+zipVoiceWithNoScale = zipVoiceWith' const  -- | -- Join the given voices by combining durations and values using the given function.@@ -451,7 +454,7 @@     merge (Just x) Nothing  = True     merge Nothing  (Just x) = True     merge (Just x) (Just y) = False-    hasOnlyRests = all isNothing $ toListOf traverse x -- norm+    hasOnlyRests = all isNothing $ toListOf traverse x -- norm   withContext :: Voice a -> Voice (Ctxt a)@@ -523,7 +526,7 @@ reverseValues :: Voice a -> Voice a reverseValues = over valuesV reverse --- Lens "filtered" throuygh a voice+-- 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) @@ -548,4 +551,184 @@ -- 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++sameDurations :: Voice a -> Voice b -> Bool+sameDurations a b = view durationsV a == view durationsV b++mergeIfSameDuration :: Voice a -> Voice b -> Maybe (Voice (a, b))+mergeIfSameDuration = mergeIfSameDurationWith (,)++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]++-- |+-- 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+--+splitLatterToAssureSameDuration :: Voice b -> Voice b -> Voice b+splitLatterToAssureSameDuration = splitLatterToAssureSameDurationWith dup+  where+    dup x = (x,x)++splitLatterToAssureSameDurationWith :: (b -> (b, b)) -> Voice b -> Voice b -> Voice b+splitLatterToAssureSameDurationWith = undefined++polyToHomophonic      :: [Voice a] -> Maybe (Voice [a])+polyToHomophonic = undefined++polyToHomophonicForce :: [Voice a] -> Voice [a]+polyToHomophonicForce = undefined++homoToPolyphonic      :: Voice [a] -> [Voice a]+homoToPolyphonic = undefined++changeCrossing   :: Ord a => Voice a -> Voice a -> (Voice a, Voice a)+changeCrossing = undefined++changeCrossingBy :: Ord b => (a -> b) -> Voice a -> Voice a -> (Voice a, Voice a)+changeCrossingBy = undefined++processExactOverlaps :: (a -> a -> (a, a)) -> Voice a -> Voice a -> (Voice a, Voice a)+processExactOverlaps = undefined++processExactOverlaps' :: (a -> b -> Either (a,b) (b,a)) -> Voice a -> Voice b -> (Voice (Either b a), Voice (Either a b))+processExactOverlaps' = undefined++onsetsRelative    :: Time -> Voice a -> [Time]+onsetsRelative = undefined++offsetsRelative   :: Time -> Voice a -> [Time]+offsetsRelative = undefined++midpointsRelative :: Time -> Voice a -> [Time]+midpointsRelative = undefined++erasRelative      :: Time -> Voice a -> [Span]+erasRelative = undefined++onsetMap  :: Time -> Voice a -> Map Time a+onsetMap = undefined++offsetMap :: Time -> Voice a -> Map Time a+offsetMap = undefined++midpointMap :: Time -> Voice a -> Map Time a+midpointMap = undefined++eraMap :: Time -> Voice a -> Map Span a+eraMap = undefined++durations :: Voice a -> [Duration]+durations = undefined++-- values :: Voice a -> [a] -- Same as Foldable.toList+-- values = undefined++++{-++sameDurations           :: Voice a -> Voice b -> Bool+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]+splitLatterToAssureSameDuration :: Voice b -> Voice b -> Voice b+splitLatterToAssureSameDurationWith :: (b -> (b, b)) -> Voice b -> Voice b -> Voice b+polyToHomophonic      :: [Voice a] -> Maybe (Voice [a])+polyToHomophonicForce :: [Voice a] -> Voice [a]+homoToPolyphonic      :: Voice [a] -> [Voice a]+joinVoice             :: Voice (Voice a) -> a+changeCrossing   :: Ord a => Voice a -> Voice a -> (Voice a, Voice a)+changeCrossingBy :: Ord b => (a -> b) -> Voice a -> Voice a -> (Voice a, Voice a)+processExactOverlaps :: (a -> a -> (a, a)) -> Voice a -> Voice a -> (Voice a, Voice a)+processExactOverlaps' :: (a -> b -> Either (a,b) (b,a)) -> Voice a -> Voice b -> (Voice (Either b a), Voice (Either a b))+onsetsRelative    :: Time -> Voice a -> [Time]+offsetsRelative   :: Time -> Voice a -> [Time]+midpointsRelative :: Time -> Voice a -> [Time]+erasRelative      :: Time -> Voice a -> [Span]+onsetMap  :: Time -> Voice a -> Map Time a+offsetMap :: Time -> Voice a -> Map Time a+midpointMap :: Time -> Voice a -> Map Time a+eraMap :: Time -> Voice a -> Map Span a+durations :: Voice a -> [Duration]+values    :: Voice a -> [a] -- Same as Foldable.toList+isPossiblyInfinite :: Voice a -> Bool+hasMelodicDissonanceWith :: (a -> a -> Bool) -> Voice a -> Bool+hasIntervalWith :: AffineSpace a => (Diff a -> Bool) -> Voice a -> Bool+hasDurationWith :: (Duration -> Bool) -> Voice a -> Bool+reifyVoice :: Voice a -> Voice (Duration, a)+mapWithIndex :: (Int -> a -> b) -> Voice a -> Voice b+mapWithDuration :: (Duration -> a -> b) -> Voice a -> Voice b+mapWithIndexAndDuration :: (Int -> Duration -> a -> b) -> Voice a -> Voice b+_ :: Iso (Voice ()) [Duration]+asingleton' :: Prism (Voice a) (Duration, a)+asingleton :: Prism (Voice a) a+separateVoicesWith :: (a -> k) -> Voice a -> Map k (Voice a)+freeVoiceR :: (forall a. -> [a] -> a)          -> Voice a -> (a, Duration)+freeVoiceRNoDur :: ([a] -> a)          -> Voice a -> a+freeVoice  :: (forall a. -> [a] -> [a])        -> Voice a -> Voice a+freeVoice2 :: (forall a. -> [a] -> [a] -> [a]) -> Voice a -> Voice a -> Voice a+empty :: Voice a+singleton :: a -> Voice a+cons :: a -> Voice a -> Voice a+snoc :: Voice a -> a -> Voice a+append :: Voice a -> Voice a -> Voice a+ap :: Voice (a -> b) -> Voice a -> Voice b+apDur :: Voice (Duration -> Duration -> a -> b) -> Voice a -> Voice b+intersperse :: Duration -> a -> Voice a -> Voice a+-- intercalate :: Voice a -> Voice (Voice a) -> Voice a+subsequences :: Voice a -> [Voice a]+permutations :: Voice a -> [Voice a]+iterate :: (a -> a) -> a -> Voice a+repeat :: a -> Voice a+replicate :: Int -> a -> Voice a+unfoldr :: (b -> Maybe (a, b)) -> b -> Voice a+Differences between Voice and Chord (except the obviously different composition styles):+  - Voice is a Monoid, Chord just a Semigroup (??)+  - TODO represent spanners using (Voice a, Map (Int,Int) s)+  Arguably this should be part of Voice+  TODO the MVoice/TVoice stuff+newtype MVoice = Voice (Maybe a)+newtype PVoice = [Either Duration (Voice a)]+expandRepeats :: [Voice (Variant a)] -> Voice a++-}