| Safe Haskell | Safe-Inferred |
|---|
Solkattu.Solkattu
Description
Notation for Carnatic solkattu.
This is actually a separate library that's independent of the rest of the sequencer. The only connection is that its final output can be stroke names for some instrument and thus easily inserted into a track.
Solkattu is a general form of rhythmic notation. Since the syllables (sollus) are independent of any particular instrument, they can express general rhythmic structures, which can then be realized in a form idiomatic to different instruments.
The system is split up in a somewhat complicated way to separate rhythmic handling from sollus, and separate realizations sollus to various instruments. The structure from low to high level is:
Solkattu.Tala - General Tala.Tala type.
Solkattu.S - Generic rhythmic framework, where the
"payload" note type is abstract. This can express rhythms in terms of
S.Speed and S.TempoChange, check them against a Tala, and realize down to
S.Duration tagged notes.
Solkattu.Solkattu - Fill in a Sequence's note with a Sollu type. This supports all of the notation in Solkattu.Dsl. As Sequence leaves the note type abstract, this leaves the instrument-dependent stroke type abstract.
Solkattu.Realize - This has an instrument-specific Stroke, which is the result of resolving the sollus. The stroke type is still abstract since it's polymorphic over the specific instrument.
Solkattu.Instrument.Mridangam, Solkattu.Instrument.KendangTunggal, etc. - These describe specific instruments for Realize.
Solkattu.Korvai - A Korvai unifies the instrument-specific Patterns and StrokeMaps together with Tala and a solkattu sequence. So I can support multiple instruments from one solkattu score, it merges the stroke types into a single type, and projects out the specific strokes depending on which instrument is being realized.
Solkattu.Dsl.Solkattu - Functions for creating solkattu scores. It defines (or replaces) various operators to make scores look nicer.
Solkattu.Score.Solkattu* - Instrument-independent korvais.
Solkattu.Dsl.Mridangam, Solkattu.Score.Mridangam* - These are similar to Dsl and Score.Solkattu*, except they use concrete mridangam strokes instead of abstract sollus.
The naming convention is that "Note" is the level-specific value,
which may have a "Note" constructor with the "next level" of value.
"SNote" is an alias for composing Note with Note, and
"Sequence" is a newtype for a list of those, but is abstractly the monoid
where you can put together notation to form a score.
Synopsis
- class (Show a, Pretty a) => Notation a where
- notation :: a -> (Styled.Style, Text)
- extension :: a -> Char
- textNotation :: Text -> (Styled.Style, Text)
- notationText :: Notation a => a -> Text
- type Error = Text
- data Note sollu
- data Group
- = GReduction !Reduction
- | GMeta !Meta
- data Reduction = Reduction {}
- data Meta = Meta {}
- meta :: GroupType -> Meta
- data GroupType
- groupTypes :: [GroupType]
- data Side
- data Space
- data NoteT sollu = NoteT {}
- data Tag
- note :: sollu -> NoteT sollu
- noteOf :: Note sollu -> Maybe (NoteT sollu)
- solluOf :: Note sollu -> Maybe sollu
- modifyNote :: (NoteT a -> NoteT b) -> Note a -> Note b
- newtype Pattern = PatternM S.Matra
- pattern :: S.Matra -> Pattern
- data Karvai
- data Sollu
- parseSollus :: Text -> Either Error [Maybe Sollu]
- allSollus :: [(Text, Sollu)]
- parseSyllables :: Show sollu => [(Text, sollu)] -> Text -> Either Error [Maybe sollu]
- parseSyllablesWord :: [(Text, sollu)] -> Text -> [[Maybe sollu]]
- durationOf :: S.HasMatras a => S.Tempo -> S.Sequence Group a -> S.Duration
- matrasOf :: S.HasMatras a => S.Tempo -> S.Sequence Group a -> S.FMatra
- _durationOf :: (S.HasMatras a, Num dur, Ord dur) => (S.Tempo -> S.Duration -> dur) -> S.Tempo -> S.Sequence Group a -> dur
- flatDuration :: S.HasMatras a => S.Flat Group a -> S.Duration
- cancelKarvai :: [S.Flat g (Note sollu)] -> [S.Flat g (Note sollu)]
- type Variations = [(S.Matra, S.Matra, S.Matra)]
- vary :: (S.Matra -> Variations) -> S.Sequence g (Note sollu) -> [S.Sequence g (Note sollu)]
- variations :: [(S.Matra, S.Matra, S.Matra) -> Bool] -> S.Matra -> Variations
- ascending :: (S.Matra, S.Matra, S.Matra) -> Bool
- descending :: (S.Matra, S.Matra, S.Matra) -> Bool
- standard :: (S.Matra, S.Matra, S.Matra) -> Bool
- allVariations :: S.Matra -> Variations
- findTriads :: S.Sequence g (Note sollu) -> [(S.Matra, (Int, Int, Int))]
- newtype Exception = Exception Text
- throw :: CallStack.Stack => Text -> a
- applyModifications :: (a -> mod -> a) -> [(Int, mod)] -> [a] -> [a]
- permuteFst :: (a -> [b]) -> [(a, x)] -> [[(b, x)]]
- check :: CallStack.Stack => Either Error a -> a
- checkMsg :: CallStack.Stack => Text -> Either Error a -> a
Documentation
class (Show a, Pretty a) => Notation a where Source #
Render a concrete stroke to text representing it. This is used for ASCII output, so it should produce only a single character per matra duration. There could be exceptions for strokes which are both rare and almost always occur before a rest.
The Show and Pretty superclasses are to make debugging more convenient.
Minimal complete definition
Methods
notation :: a -> (Styled.Style, Text) Source #
extension :: a -> Char Source #
Extend the note to fill its time with this character.
Instances
| Notation Degree Source # | |
| Notation Pitch Source # | |
| Notation Bol Source # | |
| Notation Stroke Source # | |
| Notation Stroke Source # | |
| Notation Stroke Source # | |
| Notation Thoppi Source # | |
| Notation Valantalai Source # | |
Defined in Solkattu.Instrument.Mridangam Methods notation :: Valantalai -> (Styled.Style, Text) Source # extension :: Valantalai -> Char Source # | |
| Notation Stroke Source # | |
| Notation Stroke Source # | |
| Notation Pattern Source # | |
| Notation Sollu Source # | |
| Notation stroke => Notation (Note stroke) Source # | |
| Notation stroke => Notation (Stroke stroke) Source # | |
textNotation :: Text -> (Styled.Style, Text) Source #
notationText :: Notation a => a -> Text Source #
Instances
A Group is metadata stored alongside the nested sollus, but the actual
nesting happens in S.Group. See NOTE [nested-groups] for how I arrived at
the design.
Constructors
| GReduction !Reduction | |
| GMeta !Meta |
Instances
| IsString Sequence Source # | |
Defined in Solkattu.Dsl.Bol Methods fromString :: String -> Sequence # | |
| IsString Sequence Source # | |
Defined in Solkattu.Dsl.Solkattu Methods fromString :: String -> Sequence # | |
| IsString SequenceM Source # | |
Defined in Solkattu.Dsl.Solkattu Methods fromString :: String -> SequenceM # | |
| Show Group Source # | |
| Eq Group Source # | |
| Ord Group Source # | |
| Pretty Group Source # | |
| Rest (SequenceT sollu) Source # | |
Defined in Solkattu.Dsl.Notation | |
Instances
| Show Reduction Source # | |
| Eq Reduction Source # | |
| Ord Reduction Source # | |
| Pretty Reduction Source # | |
Constructors
| Meta | |
Fields
| |
Constructors
| GGroup | A generic group, usually manually applied. |
| GReductionT |
|
| GFiller | A bit of decorative filler, should be highlighted subtly if at all. |
| GPattern | A realized |
| GExplicitPattern | A pattern with sollus already given. |
| GSarva | |
| GCheckDuration !S.Duration | Check that this group has the duration in |
Instances
| Show GroupType Source # | |
| Eq GroupType Source # | |
| Ord GroupType Source # | |
| Pretty GroupType Source # | |
groupTypes :: [GroupType] Source #
All GroupTypes that should be seen by render. GCheckDuration should
have been removed by checkDuration. I could express that in the
type, but it seems too noisy for now.
Before means drop the strokes before the _split split, After means
drop the ones after.
A note that can take up a variable amount of space. Since it doesn't have set strokes (or any, in the case of Rest), it can be arbitrarily divided.
Constructors
| Rest | |
| Offset | This is not actual rest time in the performance, but inserted in the score for a start offset. |
Constructors
| NoteT | |
Instances
| Foldable NoteT Source # | |
Defined in Solkattu.Solkattu Methods fold :: Monoid m => NoteT m -> m # foldMap :: Monoid m => (a -> m) -> NoteT a -> m # foldMap' :: Monoid m => (a -> m) -> NoteT a -> m # foldr :: (a -> b -> b) -> b -> NoteT a -> b # foldr' :: (a -> b -> b) -> b -> NoteT a -> b # foldl :: (b -> a -> b) -> b -> NoteT a -> b # foldl' :: (b -> a -> b) -> b -> NoteT a -> b # foldr1 :: (a -> a -> a) -> NoteT a -> a # foldl1 :: (a -> a -> a) -> NoteT a -> a # elem :: Eq a => a -> NoteT a -> Bool # maximum :: Ord a => NoteT a -> a # minimum :: Ord a => NoteT a -> a # | |
| Traversable NoteT Source # | |
| Functor NoteT Source # | |
| Show sollu => Show (NoteT sollu) Source # | |
| Eq sollu => Eq (NoteT sollu) Source # | |
| Ord sollu => Ord (NoteT sollu) Source # | |
Defined in Solkattu.Solkattu | |
| Pretty sollu => Pretty (NoteT sollu) Source # | |
A sollu can have a tag attached. This is used to map certain sets of sollus to a different realization. The idea is that even though the sollus are the same, they may be realized different ways in different contexts.
Constructors
| Tag !Int | |
| Middle | Marks the middle karvai in a tirmanam. This is applied automatically, so it can have an alternate realization. |
| Standard | Marks a standard pattern. This isolates the "standard pattern" use of common sollus like taka. |
Constructors
| NoSollu | a dummy sollu for rests in Konnakol |
| Cham | |
| Dheem | |
| Dhom | |
| Di | |
| Dim | |
| Din | |
| Dit | |
| Du | |
| Ga | |
| Gin | |
| Gu | |
| Jo | |
| Ka | |
| Ki | |
| Ku | |
| Kum | |
| Lang | |
| Mi | |
| Na | |
| Nam | |
| Nang | |
| Nu | |
| Ri | |
| Ta | |
| Tam | |
| Tang | |
| Tong | |
| Tat | |
| Tha | |
| Thom | |
| Ti |
Instances
| IsString Sequence Source # | |
Defined in Solkattu.Dsl.Solkattu Methods fromString :: String -> Sequence # | |
| Bounded Sollu Source # | |
| Enum Sollu Source # | |
Defined in Solkattu.Solkattu | |
| Show Sollu Source # | |
| Eq Sollu Source # | |
| Ord Sollu Source # | |
| Expr.ToExpr Sollu Source # | |
Defined in Solkattu.Instrument.Konnakol | |
| Notation Sollu Source # | |
| Pretty Sollu Source # | |
| Expr.ToExpr (Stroke Sollu) Source # | |
Defined in Solkattu.Instrument.Konnakol | |
parseSollus
durations
durationOf :: S.HasMatras a => S.Tempo -> S.Sequence Group a -> S.Duration Source #
matrasOf :: S.HasMatras a => S.Tempo -> S.Sequence Group a -> S.FMatra Source #
_durationOf :: (S.HasMatras a, Num dur, Ord dur) => (S.Tempo -> S.Duration -> dur) -> S.Tempo -> S.Sequence Group a -> dur Source #
flatDuration :: S.HasMatras a => S.Flat Group a -> S.Duration Source #
Unfortunately, with Reduction and GSarva groups, the notes don't reflect
the actual durations, so for Group-bearing S.Flat, I need a special
function. I tried really hard to prevent this but failed. The sollus have
to go in the note field, and with reductions and sarva, they no longer
correspond exactly to realized strokes. I would have to two note slots,
one for a space-filling Group FMatras, and another for the sollus, but
since groups can be nested, it gets really head-hurting for my tiny brain.
See NOTE [nested-groups] for chaotic details.
functions
cancelKarvai :: [S.Flat g (Note sollu)] -> [S.Flat g (Note sollu)] Source #
A Karvai Note followed by a Space will replace the rest, if followed by
a Note or Pattern, the Karvai will be dropped. Since a Karvai note
logically has no duration, if it's the last note it will be dropped
vary
Arguments
| :: (S.Matra -> Variations) | variations allowed for this duration |
| -> S.Sequence g (Note sollu) | |
| -> [S.Sequence g (Note sollu)] |
Variation means replacing a triad of patterns of the same duration with a an increasing or decreasing sequence. For instance, 666 can become 567, 765, or 777 can become 678 or 579 or their inverses.
TODO Variation on a higher order is also possible, so for instance 777, 777, 777 may become 666, 777, 888
TODO Also we have 5, 55, 555 -> 55, 55, 55 -> 555, 55, 5. This actually applies to more than just Patterns, e.g. 3 as tadin_. I think this is orthogonal and could get a different function.
variations :: [(S.Matra, S.Matra, S.Matra) -> Bool] -> S.Matra -> Variations Source #
allVariations :: S.Matra -> Variations Source #
findTriads :: S.Sequence g (Note sollu) -> [(S.Matra, (Int, Int, Int))] Source #
Find triples of Patterns with the same length and return their indices. The indices are in ascending order.
exceptions
Yes, I use impure exceptions, because otherwise the DSL has to become monadic or at least applicative. But it seems less egregious because there isn't such a strong distinction between compiling and running anyway.
But it does mean I have to be careful to force and catch at the boundaries.
Instances
| Exception.Exception Exception Source # | |
Defined in Solkattu.Solkattu Methods toException :: Exception -> Exception.SomeException # fromException :: Exception.SomeException -> Maybe Exception # displayException :: Exception -> String # | |
| Show Exception Source # | |
| Eq Exception Source # | |
throw :: CallStack.Stack => Text -> a Source #
util
Arguments
| :: (a -> mod -> a) | |
| -> [(Int, mod)] | modifications along with their indices, in ascending order |
| -> [a] | |
| -> [a] |
permuteFst :: (a -> [b]) -> [(a, x)] -> [[(b, x)]] Source #