Karya, built on Mon Jul 24 11:39:07 PDT 2017 (patch 33511aca01257b76b88de7c7a2763b7a965c084e)

Safe HaskellNone

Perform.Lilypond.Process

Contents

Description

Convert Lilypond Events to lilypond code.

It's a terrible name, but what else am I supposed to call it? Render? Realize? Perform?

Synopsis

Documentation

simple_articulations :: [(Attrs.Attributes, Code)] Source #

Automatically add lilypond code for certain attributes.

modal_articulations :: [(Attrs.Attributes, Code, Code)] Source #

Certain attributes are modal, in that they emit one thing when they start, and another when they stop.

convert_to_rests

convert_to_rests :: [VoiceLy] -> [Ly] Source #

Convert a staff to all rests, keeping the key, clef, and meter changes. have predicates that recognize those, and keep those Codes

process

run_process :: Monad m => m [b] -> ([a] -> m ([b], [a])) -> [a] -> m [b] Source #

process Source #

Arguments

:: Types.Config 
-> Types.Time 
-> [Meter.Meter]

one for each measure

-> [Types.Event] 
-> Either.Either Text [VoiceLy] 

This figures out timing and emits a stream of lilypond code.

simple_convert :: Types.Config -> Meter.Meter -> Types.Time -> [Types.Event] -> [Ly] Source #

This is a simplified version of convert, designed for converting little chunks of lilypond that occur in other expressions. So it doesn't handle clef changes, meter changes, or even barlines. It will apply simple_articulations, but not modal_articulations.

convert chunk

mix_in_code :: Types.Time -> [Types.Event] -> [Ly] -> [Ly] Source #

Code events are mixed into the Lys, depending on their prepend or append attrs.

This is doing the same thing as make_lys, but since rests aren't represented explicitly be events as notes are, I have to first generate the notes, and then mix in the code afterwards.

mix_in_code_voices :: Types.Time -> [Types.Event] -> [VoiceLy] -> [VoiceLy] Source #

This is the same thing as mix_in_code, except it has to mix code into [VoiceLy], which is more complicated. The duplicated logic is pretty unfortunate but I couldn't think of a way to get rid of it. See collect_voices for more information.

convert_chord

convert_chord :: Meter.Meter -> NonEmpty.NonEmpty Types.Event -> ConvertM ([Ly], [Types.Event]) Source #

This is the lowest level of conversion. It converts a vertical slice of notes.

make_lys Source #

Arguments

:: Types.Time 
-> Attrs.Attributes 
-> Meter.Meter 
-> NonEmpty.NonEmpty Types.Event 
-> ([Ly], Types.Time, Attrs.Attributes, [Types.Event])

(note, note end time, last attrs, remaining events)

Convert a chunk of events all starting at the same time. Events with 0 duration or null pitch are expected to have either Constants.v_ly_prepend or Constants.v_ly_append_all, and turn into Code Notes.

The rules are documented in convert_event.

make_note Source #

Arguments

:: Types.Time 
-> Attrs.Attributes 
-> Meter.Meter 
-> NonEmpty.NonEmpty Types.Event

Events that occur at the same time. All these events must have >0 duration!

-> Maybe.Maybe Types.Time 
-> (Ly, Types.Time, [Types.Event])

(note, note end time, clipped)

convert voices

collect_voices

collect_voices :: [Types.Event] -> Either.Either Text (VoiceMap Types.Event, [Types.Event], [Types.Event]) Source #

Span events until they don't have a v_voice val.

I used to mix the code into the first voice here, but simplify_voices may then get rid of it. So return the code events and mix them in after simplification.

span_voices :: [Types.Event] -> ([Either.Either Types.Event (Either.Either Text Int, Types.Event)], [Types.Event]) Source #

Strip off events with voices. This is complicated by the possibility of intervening zero_dur code events.

voices_to_ly

voices_to_ly :: VoiceMap Types.Event -> ConvertM (VoiceMap Ly) Source #

Like convert, but converts within a voice, which means no nested voices are expected.

simplify_voices :: VoiceMap Ly -> [VoiceLy] Source #

If a whole measure of a voice is empty, omit the voice for that measure.

Previously, I tried a more fine-grained approach, documented in span_voices. This way is more complicated because it has to operate on Lys since it needs to know where the measure boundaries are, but gives much better results.

split_voices_at :: [Types.Time] -> VoiceMap Ly -> [VoiceMap Ly] Source #

Split voices every place any of them has a full measure rest.

[(1, xs), (2, ys)] -> [(1, x), (2, y)], [(1, x), (2, y)]
[(1, xs), (2, ys)] -> [(1, [xs]), (2, [ys])]

ly_start_times :: Types.Time -> [Ly] -> [Types.Time] Source #

drop 1 for end times.

misc

rests_until :: Types.Time -> ConvertM [Ly] Source #

Pad with rests until given Time, which is not necessarily on a measure boundary.

advance_measure :: Types.Time -> ConvertM (Maybe.Maybe Ly) Source #

Advance now to the given time, up to and including the end of the measure, but no further. Return Ly with a Barline if this is a new measure.

If I wanted to emit Barlines automatically I'd have to collect the output [Ly] in the State, which I'd then need to parameterize since it can be [VoiceLy] too.

ConvertM

data State Source #

Constructors

State 

Fields

Instances

util

types

data Ly Source #

Instances

Show Ly # 

Methods

showsPrec :: Int -> Ly -> ShowS #

show :: Ly -> String #

showList :: [Ly] -> ShowS #

Pretty Ly # 
Types.ToLily Ly # 

Methods

to_lily :: Ly -> Text Source #

Note

data Note Source #

Constructors

Note 

Fields

Instances

data Tie Source #

Constructors

NoTie 
TieNeutral 
TieUp 
TieDown 

Instances

Show Tie # 

Methods

showsPrec :: Int -> Tie -> ShowS #

show :: Tie -> String #

showList :: [Tie] -> ShowS #

Types.ToLily Tie # 

Methods

to_lily :: Tie -> Text Source #

type Code = Text Source #

Arbitrary bit of lilypond code. This type isn't used for non-arbitrary chunks, like note_pitch.

Rest

data Rest Source #

Constructors

Rest 

Fields

Instances

data RestType Source #

Constructors

NormalRest 
FullMeasure !Types.Duration !Int

Unlike other rests, FullMeasure rests have their duration encoded. It's redundant with rest_duration, but should always be the same.

HiddenRest 

Key

data Key Source #

Constructors

Key !Text !Mode 

Instances

Eq Key # 

Methods

(==) :: Key -> Key -> Bool #

(/=) :: Key -> Key -> Bool #

Show Key # 

Methods

showsPrec :: Int -> Key -> ShowS #

show :: Key -> String #

showList :: [Key] -> ShowS #

Types.ToLily Key # 

Methods

to_lily :: Key -> Text Source #

type Mode = Text Source #

voice

newtype Voices Source #

Each Ly list should be the same duration and have the same number of barlines.

Constructors

Voices (VoiceMap Ly) 

type VoiceMap a = [(Voice, [a])] Source #

Voices shouldn't be repeated, so this would be more appropriate as a Map Voice [a], but it turns out all the consumers work best with a list so list it is.

data Voice Source #

Instances

Event

clip_event :: Types.Time -> Types.Event -> Maybe.Maybe Types.Event Source #

Clip off the part of the event before the given time, or Nothing if it was entirely clipped off.