Safe Haskell | Safe-Inferred |
---|
Low level support for rhythmic sequences in a Tala. The actual Note type is polymorphic, so this is purely rhythmic.
Synopsis
- data Note g a
- = Note !a
- | TempoChange !TempoChange ![Note g a]
- | Group !g ![Note g a]
- data TempoChange
- data Sequence g a
- singleton :: Note g a -> Sequence g a
- null :: Sequence g a -> Bool
- fromList :: [Note g a] -> Sequence g a
- toList :: Sequence g a -> [Note g a]
- mapS :: (Note g1 a1 -> Note g2 a2) -> Sequence g1 a1 -> Sequence g2 a2
- apply :: ([Note g1 a1] -> [Note g2 a2]) -> Sequence g1 a1 -> Sequence g2 a2
- replace :: (Eq g, Eq a) => Sequence g a -> Sequence g a -> Sequence g a -> Sequence g a
- data Duration
- data FMatra
- type Matra = Int
- type Speed = Int
- type Nadai = Int
- type Stride = Int
- speedFactor :: Speed -> Duration
- changeSpeed :: Speed -> [Note g a] -> Note g a
- class HasMatras a where
- matrasOf :: a -> Matra
- hasSustain :: a -> Bool
- mapGroup :: (g -> h) -> Note g a -> Note h a
- flattenGroups :: [Note g a] -> [Note h a]
- simplify :: [Note g a] -> [Note g a]
- map1 :: (a -> a) -> Note g a -> Note g a
- filterNotes :: (a -> Bool) -> Sequence g a -> Sequence g a
- dropEndWhile :: (a -> Bool) -> Sequence g a -> Sequence g a
- data Tempo = Tempo {}
- defaultTempo :: Tempo
- changeTempo :: TempoChange -> Tempo -> Tempo
- decompose :: Duration -> Either Text [Speed]
- decomposeM :: FMatra -> Either Text [Speed]
- data Flat g a
- filterFlat :: (a -> Bool) -> [Flat g a] -> [Flat g a]
- mapGroupFlat :: (g -> h) -> [Flat g a] -> [Flat h a]
- notes :: [Note g a] -> [a]
- flatten :: [Note g a] -> [Flat g a]
- flattenWith :: Tempo -> [Note g a] -> [Flat g a]
- flattenedNotes :: [Flat g a] -> [a]
- flatToState :: (Flat g a -> Duration) -> Tala.Akshara -> State -> [Flat g a] -> (State, [(State, Flat g a)])
- withDurations :: HasMatras a => [Flat g a] -> [Flat g (Duration, a)]
- tempoNotes :: [Flat g a] -> [(Tempo, a)]
- maxSpeed :: [Flat g a] -> Speed
- tempoToState :: HasMatras a => Tala.Akshara -> Duration -> [(Tempo, a)] -> (State, [(State, a)])
- data Stroke a
- normalizeSpeed :: HasMatras a => Speed -> Tala.Akshara -> [Flat g a] -> [Flat g (State, Stroke a)]
- flattenSpeed :: HasMatras a => Speed -> [Note g a] -> Either Text [Note g (Stroke a)]
- data State = State {
- stateAvartanam :: !Int
- stateAkshara :: !Tala.Akshara
- stateMatra :: !Duration
- stateTempo :: !Tempo
- statePosition :: State -> (Int, Tala.Akshara, Duration)
- stateMatraPosition :: State -> Duration
- stateAbsoluteAkshara :: Tala.Akshara -> State -> Duration
- stateFrom :: Tala.Akshara -> Duration -> State
- showPosition :: State -> Text
- durationOf :: HasMatras a => Tempo -> Note g a -> Duration
- noteDuration :: HasMatras a => Tempo -> a -> Duration
- noteFMatra :: HasMatras a => Tempo -> Note g a -> FMatra
- fmatraDuration :: Tempo -> FMatra -> Duration
- durationFMatra :: Tempo -> Duration -> FMatra
- matraFMatra :: Tempo -> Matra -> FMatra
- matraDuration :: Tempo -> Duration
Documentation
Note !a | |
TempoChange !TempoChange ![Note g a] | |
Group !g ![Note g a] |
Instances
Foldable (Note g) Source # | |
Defined in Solkattu.S fold :: Monoid m => Note g m -> m # foldMap :: Monoid m => (a -> m) -> Note g a -> m # foldMap' :: Monoid m => (a -> m) -> Note g a -> m # foldr :: (a -> b -> b) -> b -> Note g a -> b # foldr' :: (a -> b -> b) -> b -> Note g a -> b # foldl :: (b -> a -> b) -> b -> Note g a -> b # foldl' :: (b -> a -> b) -> b -> Note g a -> b # foldr1 :: (a -> a -> a) -> Note g a -> a # foldl1 :: (a -> a -> a) -> Note g a -> a # elem :: Eq a => a -> Note g a -> Bool # maximum :: Ord a => Note g a -> a # minimum :: Ord a => Note g a -> a # | |
Traversable (Note g) Source # | |
Functor (Note g) Source # | |
Rest (SNote sollu) Source # | |
Defined in Solkattu.Dsl.Notation | |
(Show a, Show g) => Show (Note g a) Source # | |
(Eq a, Eq g) => Eq (Note g a) Source # | |
(Ord a, Ord g) => Ord (Note g a) Source # | |
(Pretty.Pretty a, Pretty.Pretty g) => Pretty.Pretty (Note g a) Source # | |
data TempoChange Source #
Relative speed change. Each positive number doubles the number of
Matra
s per akshara. Negative numbers halve them.
Instances
Show TempoChange Source # | |
Defined in Solkattu.S showsPrec :: Int -> TempoChange -> ShowS # show :: TempoChange -> String # showList :: [TempoChange] -> ShowS # | |
Eq TempoChange Source # | |
Defined in Solkattu.S (==) :: TempoChange -> TempoChange -> Bool # (/=) :: TempoChange -> TempoChange -> Bool # | |
Ord TempoChange Source # | |
Defined in Solkattu.S compare :: TempoChange -> TempoChange -> Ordering # (<) :: TempoChange -> TempoChange -> Bool # (<=) :: TempoChange -> TempoChange -> Bool # (>) :: TempoChange -> TempoChange -> Bool # (>=) :: TempoChange -> TempoChange -> Bool # max :: TempoChange -> TempoChange -> TempoChange # min :: TempoChange -> TempoChange -> TempoChange # | |
Pretty.Pretty TempoChange Source # | |
Defined in Solkattu.S pretty :: TempoChange -> Text Source # format :: TempoChange -> Doc Source # formatList :: [TempoChange] -> Doc Source # |
Instances
IsString Sequence Source # | |
Defined in Solkattu.Dsl.Bol fromString :: String -> Sequence # | |
IsString Sequence Source # | |
Defined in Solkattu.Dsl.Solkattu fromString :: String -> Sequence # | |
IsString SequenceM Source # | |
Defined in Solkattu.Dsl.Solkattu fromString :: String -> SequenceM # | |
Functor (Sequence g) Source # | |
Rest (SequenceT sollu) Source # | |
Defined in Solkattu.Dsl.Notation | |
Monoid (Sequence g a) Source # | |
Semigroup (Sequence g a) Source # | |
(Show a, Show g) => Show (Sequence g a) Source # | |
(Eq a, Eq g) => Eq (Sequence g a) Source # | |
(Pretty.Pretty a, Pretty.Pretty g) => Pretty.Pretty (Sequence g a) Source # | |
A single Duration unit is equivalent to 1 Akshara. Unlike FMatra
and
Matra
, this is an absolute duration, so it doesn't depend on _nadai
or
_speed
.
This is a fractional Matra
. The reason to need a fraction matra is if
there are speed changes below, so often this is used to mean toplevel matra,
which is to say duration / nadai, in which case it's relative to nadai, not
speed. But not always! Sometimes it's used to name a number of Matras
where it's assumed they have speed changes to accommodate the fraction.
A matra is an akshara divided by the nadai. It corresponds to a single sollu in first speed, which means the actual duration is dependent on Nadai and Speed.
Matra being integral is important, since together with TempoChange, it can encode the invariant that durations are always a power of two rational, once you multiply out the nadai.
0 means nadai matras per akshara. Positive numbers double that and negative ones halve it.
speedFactor :: Speed -> Duration Source #
class HasMatras a where Source #
matrasOf :: a -> Matra Source #
hasSustain :: a -> Bool Source #
True if this note has a duration in time. Otherwise, it's a single stroke, which logically has zero duration. This only affects how the note is drawn and whether it becomes a tracklang event with duration.
transform
flattenGroups :: [Note g a] -> [Note h a] Source #
simplify :: [Note g a] -> [Note g a] Source #
Drop empty TempoChanges, combine nested ones. Drop empty groups.
tempo
defaultTempo :: Tempo Source #
changeTempo :: TempoChange -> Tempo -> Tempo Source #
decompose :: Duration -> Either Text [Speed] Source #
Given a duration, return the speeds of 1 duration notes needed to add up to that duration. Error if the speed went past 4, which means the duration probably isn't binary.
flatten
This is an intermediate structure where TempoChange has been flattened out. A flat list is easier to deal with, especially since I need to match and replace sections of notes, which may overlap tempo groups arbitrarily.
However, FGroup
is actually nested, not flat. Oops. Originally it was
flat too, with a count to indicate the scope, with Tempo in a Meta type.
I still needed to express the tempo and group order, so I added a separate
FGroup, and then it got complicated to keep the count up to date when the
children changed size, and process things recursively and it seemed like
recursive data would make that simpler again. I only replace sections of
notes within group boundaries, so it doesn't need to be flat like
TempoChange does.
It turns out it's still annoying to modify trees though, evidence in
cancelKarvai
.
Another way to look at this, is that each FNote is one Matra.
mapGroupFlat :: (g -> h) -> [Flat g a] -> [Flat h a] Source #
flattenedNotes :: [Flat g a] -> [a] Source #
flatToState :: (Flat g a -> Duration) -> Tala.Akshara -> State -> [Flat g a] -> (State, [(State, Flat g a)]) Source #
Convert events with Tempo into events with absolute positions in State
.
I need to look in the group to know what the actual duration is, unfortunately.
withDurations :: HasMatras a => [Flat g a] -> [Flat g (Duration, a)] Source #
Calculate Duration for each note.
TODO this is wrong in general because unfortunately groups can affect
duration, as in flatToState
. I think I only call it after Koravi.realize,
at which point the notes do reflect the duration, but of course that's not
reflected in the types. flatDuration
has some details.
tempoNotes :: [Flat g a] -> [(Tempo, a)] Source #
Convert events with Tempo into events with absolute positions in State
.
This is only correct when the group doesn't affect duration. Since there's no group in here, presumably it's already been stripped out, which of you should only have done if it's no longer needed, which is the case post realize.
normalizeSpeed :: HasMatras a => Speed -> Tala.Akshara -> [Flat g a] -> [Flat g (State, Stroke a)] Source #
Normalize to the fastest speed. Fill slower strokes in with rests. Speed 0 always gets at least one Stroke, even if it's not the slowest.
This normalizes speed, not nadai, because Realize.format lays out notation by nadai, not in absolute time.
flattenSpeed :: HasMatras a => Speed -> [Note g a] -> Either Text [Note g (Stroke a)] Source #
This is similar to normalizeSpeed
, but working on Note
s instead of
Flat
s. Expand speed to the given toSpeed, or error if there's a speed
above it, or if I run into a nadai change. This will eliminate all
Note
s.
State
Keep track of timing and tala position.
State | |
|
statePosition :: State -> (Int, Tala.Akshara, Duration) Source #
stateMatraPosition :: State -> Duration Source #
Number of aksharas relative to the avartanam.
stateAbsoluteAkshara :: Tala.Akshara -> State -> Duration Source #
Absolute number of aksharas from the beginning of the sequence.
showPosition :: State -> Text Source #
Show avartanam, akshara, and matra as avartanam:akshara+n/d.
functions
durationOf :: HasMatras a => Tempo -> Note g a -> Duration Source #
Flatten the note and return its Duration.