proto-voice-model-0.1.0.0
Safe HaskellSafe-Inferred
LanguageGHC2021

PVGrammar.Generate

Description

This module contains functions for the generative aspects of protovoice derivations:

  • manually constructing protovoice operations (see PVGrammar) using a monadic interface
  • applying ("replaying") these operations.
Synopsis

Manually Constructing Derivations

The functions in this section can be used to manually construct individual derivation operations or in conjunction with the (indexed-)monadic functions in Common (see buildDerivation) to manually construct complete derivations. Each outer-structure operation (mkSplit, mkSpread, mkFreeze) enters a writer monad in which inner-structure operations can be chained to determine the details.

Note that the legality of the operations is not always checked, so be careful!

Freeze

mkFreeze :: Freeze Source #

Create a freeze operation (alias for FreezeOp). Can be used together with the freeze action within a monadic derivation.

Split

mkSplit :: Writer (Split n) a -> Split n Source #

Create a split operation monadically

mkSplit $ do
  ... -- internal split actions

Can be used together with the split action within a monadic derivation.

splitRegular Source #

Arguments

:: (Ord n, Hashable n) 
=> StartStop n

left parent

-> StartStop n

right parent

-> n

the new child note

-> DoubleOrnament

the ornament type of the child note

-> Bool

keep the left child edge (left parent to child)?

-> Bool

keep the right child edge (child to right parent)?

-> Writer (Split n) () 

During a split, split an existing regular edge between two notes.

splitPassing Source #

Arguments

:: (Ord n, Hashable n) 
=> n

left parent

-> n

right parent

-> n

the new child note

-> PassingOrnament

the ornament type of the child note

-> Bool

keep the left child edge (if step)

-> Bool

keep the right child edge (if step)

-> Writer (Split n) () 

During a split, split an existing passing edge, introducing a new passing note.

addToLeft Source #

Arguments

:: (Ord n, Hashable n) 
=> n

parent (from the left slice)

-> n

the new child note

-> RightOrnament

the new child note's ornament type

-> Bool

keep the new edge?

-> Writer (Split n) () 

During a split, add a new single-sided ornament to a left parent note.

addToRight Source #

Arguments

:: (Ord n, Hashable n) 
=> n

parent (from the right slice)

-> n

the new child note

-> LeftOrnament

the new child note's ornament type

-> Bool

keep the new edge?

-> Writer (Split n) () 

During a split, add a new single-sided ornament to a right parent note.

addPassingLeft Source #

Arguments

:: (Ord n, Hashable n) 
=> n

note from the left parent slice

-> n

note from the child slice

-> Writer (Split n) () 

During a split, add a new passing edge between the left parent slice and the child slice.

addPassingRight Source #

Arguments

:: (Ord n, Hashable n) 
=> n

note from the child slice

-> n

note from the right parent slice

-> Writer (Split n) () 

During a split, add a new passing edge between the child slice and the right parent slice.

Spread

mkSpread :: Writer (Endo (Spread n)) () -> Spread n Source #

Create a spread operation monadically

mkSpread $ do
  ... -- internal spread actions

Can be used together with the spread action within a monadic derivation.

spreadNote Source #

Arguments

:: (Ord n, Hashable n) 
=> n

the parent note

-> SpreadDirection

the distribution of the note

-> Bool

introduce a repetition edge (if possible)?

-> Writer (Endo (Spread n)) () 

During a spread, distribute one of the parent notes to the child slices of a spread.

addPassing Source #

Arguments

:: (Ord n, Hashable n) 
=> n

the left end of the edge

-> n

the right end of the edge

-> Writer (Endo (Spread n)) () 

During a spread, add a new passing edge between the child slices of a spread.

addOctaveRepetition Source #

Arguments

:: (Ord n, Hashable n) 
=> n

the left end of the edge

-> n

the right end of the edge

-> Writer (Endo (Spread n)) () 

During a spread, add a new repetition edge between two notes of the same pitch class but from different octaves.

Derivation Players

These players can be used with the replay functions in the Display module to obtain derivation graphs for protovoice derivations.

derivationPlayerPV :: (Eq n, Ord n, Notation n, Hashable n, Eq (IntervalOf n), HasPitch n) => DerivationPlayer (Split n) Freeze (Spread n) (Notes n) (Edges n) Source #

A derivation player for protovoices. The default version of the PV player drops all edges that are not used later on when generating child transitions. This behaviour matches the intermediate representation of the parsers, which only track edges that are necessary to explain the downstream notes. If you want to generate all edges (i.e., all functional relations between notes) use derivationPlayerPVAllEdges.

derivationPlayerPVAllEdges :: (Eq n, Ord n, Notation n, Hashable n, Eq (IntervalOf n), HasPitch n) => DerivationPlayer (Split n) Freeze (Spread n) (Notes n) (Edges n) Source #

A derivation player for protovoices that produces all edges that express a functional relation between two notes. For a version that only produces "necessary" edges, use derivationPlayerPV.

Applying Operations

Apply operations to parent objects and get the resulting child objects.

applySplit Source #

Arguments

:: forall n. (Ord n, Notation n, Hashable n) 
=> Split n

the split operation

-> Edges n

the parent transition

-> Either String (Edges n, Notes n, Edges n)

the resulting child transitions and slice (or an error message).

Tries to apply a split operation to the parent transition.

applySplitAllEdges :: forall n. (Ord n, Notation n, Hashable n) => Split n -> Edges n -> Either String (Edges n, Notes n, Edges n) Source #

A variant of applySplit that inserts all protovoice edges into the child transitions, even those that are not "kept" (used for further elaboration). This is useful when you want to see all relations between notes in the piece.

applyFreeze Source #

Arguments

:: (Eq (IntervalOf n), HasPitch n) 
=> Freeze

the freeze operation

-> Edges n

the unfrozen edge

-> Either String (Edges n)

the frozen transition

Tries to apply a freeze operation to a transition.

applySpread Source #

Arguments

:: forall n. (Ord n, Notation n, Hashable n) 
=> Spread n

the spread operation

-> Edges n

the left parent transition

-> Notes n

the parent slice

-> Edges n

the right parent transition

-> Either String (Edges n, Notes n, Edges n, Notes n, Edges n)

the child transitions and slices (or an error message)

Tries to apply a spread operation to the parent transitions and slice.

freezable :: (Eq (IntervalOf n), HasPitch n) => Edges n -> Bool Source #

Indicates whether a transition can be frozen (i.e., doesn't contain non-"tie" edges).

Utility Functions

debugPVAnalysis :: (Notation n, Ord n, Hashable n, HasPitch n, Eq (IntervalOf n)) => PVAnalysis n -> IO (Either String ()) Source #

A specialized version of debugAnalysis for protovoice derivations. Prints the steps and intermediate configurations of a derivation.

checkDerivation :: (Ord n, Notation n, Hashable n, Eq (IntervalOf n), HasPitch n, Show n) => [Leftmost (Split n) Freeze (Spread n)] -> Path [n] [Edge n] -> Bool Source #

Compares the output of a derivation with the original piece (as provided to the parser). Returns True if the output matches the original and False if the output doesn't match or the derivation is invalid.