Copyright | (c) 2022 Andrew A. Cashner |
---|---|
Stability | Experimental |
Safe Haskell | None |
Language | Haskell2010 |
Scribo.MEI
Contents
Description
This module is our implementation of Kircher's palimpsest phonotacticum, his
system for writing out the music created using the ark. Certain elements that
Kircher used notation to calculate (like determining vocal ranges by clef
combinations and the size of the staff) we actually do in the Cogito
module.
This module is purely focused on output of complete music information to a
music-notation language.
This module outputs in the XML format of the Music Encoding Initiative (MEI).
This means that the whole arca program is transforming an input XML document with the text and parameters into and output XML document with the text matched to music.
Synopsis
- enbrace :: String -> String -> String -> String
- xmltagOpen :: String -> String
- xmltagClose :: String -> String
- xmlWrap :: String -> [String] -> String -> String
- xmlWrapBasic :: String -> [String] -> String
- element :: String -> [String] -> String
- attr :: String -> String -> String
- elementAttr :: String -> [String] -> [String] -> String
- note2mei :: Note -> String
- meiPname :: Pitch -> String
- meiOct :: Pitch -> String
- meiDur :: Pitch -> String
- meiAccid :: Pitch -> String
- meiSyllable :: Syllable -> String
- data ListPosition
- positionMap :: ((ListPosition, a1) -> [a2]) -> [a1] -> [a2]
- markedEnds :: [a] -> [(ListPosition, a)]
- phrase2mei :: (ListPosition, MusicPhrase) -> String
- sentence2mei :: (ListPosition, MusicSentence) -> String
- section2mei :: Arca -> (ListPosition, MusicSection) -> String
- chorus2mei :: Arca -> (ListPosition, MusicChorus) -> String
- meiKey :: Tone -> ToneSystem -> String
- meiKeyAttr :: Tone -> ToneSystem -> String
- meiKeySigString :: Tone -> ToneSystem -> String
- meiMeter :: MusicMeter -> String
- meiMeterAttr :: MusicMeter -> String
- meiMeterModern :: MusicMeter -> String
- meiMeterMensural :: MusicMeter -> String
- meiMeterMensuralAttr :: MusicMeter -> String
- meiMidiTempo :: MusicMeter -> String
- meiMidiBPM :: MusicMeter -> String
- chorus2list :: MusicChorus -> [MusicSection]
- score2mei :: Arca -> ArkMetadata -> MusicScore -> String
- meiDoubleBar :: String
- meiFinalBar :: String
- meiBarline :: String -> String
- _xmlHeader :: [Char]
- _meiVersion :: [Char]
- _whoami :: [Char]
- _Kircher :: [Char]
- _projectDesc :: [Char]
- midiInstrumentNum :: Int -> String
- _midiInstrument :: String
- meiDocument :: String -> String -> String -> String -> String -> String -> String
Write XML
Utilities
Put a string between two other strings
Create elements and attributes, and elements with attributes
Create an XML element (which may contain other elements).
If you need attributes, use elementAttr
.
Arguments
:: String | name |
-> [String] | list of attributes created with |
-> [String] | values (list of contents, including other elements) |
-> String |
Create an XML element that has attributes, e.g., class="foo"bar/p
Serialize our data structures to MEI
Note
becomes note
(pitch with syllable, or rest)
Conversions for Note
members
meiDur :: Pitch -> String Source #
Convert Dur
to MEI dur
(base value of duration) and @dots (if any;
omit if not)
meiAccid :: Pitch -> String Source #
Convert our Accid
to MEI accid
(omit if natural)
TODO Verovio will display the accidental if the accid
attribute or
element is present, regardless of the key signature. We would need to check
the tone/key and then use accid.ges for accidentals that are in the key
signature.
Conversions for lyrics
meiSyllable :: Syllable -> String Source #
If a word is a single syllable, we do not need to include @con
or
@wordpos
; if it is more than one syllable, we include these attributes.
We use a dash connector by default, and get the word position from the data
in the Syllable
type.
Write large groups to MEI
data ListPosition Source #
Where is this item in the list that contains it?
Constructors
ListHead | head of list |
ListBody | neither head nor last |
ListEnd | last item in list |
ListOnly | only item of a one-item list |
Instances
Enum ListPosition Source # | |
Defined in Scribo.MEI Methods succ :: ListPosition -> ListPosition # pred :: ListPosition -> ListPosition # toEnum :: Int -> ListPosition # fromEnum :: ListPosition -> Int # enumFrom :: ListPosition -> [ListPosition] # enumFromThen :: ListPosition -> ListPosition -> [ListPosition] # enumFromTo :: ListPosition -> ListPosition -> [ListPosition] # enumFromThenTo :: ListPosition -> ListPosition -> ListPosition -> [ListPosition] # | |
Eq ListPosition Source # | |
Defined in Scribo.MEI | |
Show ListPosition Source # | |
Defined in Scribo.MEI Methods showsPrec :: Int -> ListPosition -> ShowS # show :: ListPosition -> String # showList :: [ListPosition] -> ShowS # |
positionMap :: ((ListPosition, a1) -> [a2]) -> [a1] -> [a2] Source #
Given a function that takes a ListPosition argument and a list, apply the function to the list. This allows you to treat the first and last items in the list differently.
markedEnds :: [a] -> [(ListPosition, a)] Source #
Mark a list with the positions of the items: first, body, and last.
Output a list of pairs with the ListPosition
and the original list item.
phrase2mei :: (ListPosition, MusicPhrase) -> String Source #
Make an XML string containing a list of note
elements out of a
MusicPhrase
; end each phrase with barline
, except for last in the list.
Leave the barline of the last phrase up to the next-higher function (end of sentence gets regular bar; end of sentence, double bar; end of section, final bar).
sentence2mei :: (ListPosition, MusicSentence) -> String Source #
Make an XML string containing all the contents of one layer
out of a
MusicSentence
.
If this is the last sentence in the section, omit the bar so the higher
function calling this one can add it.
Sentence ends with regular barline.
section2mei :: Arca -> (ListPosition, MusicSection) -> String Source #
A MusicSection
contains all the music for one section, /for a single
voice/: so combine all subdivisions into one staff
and layer
so this
can be made part of an MEI section
in chorus2mei
.
Include MEI 1-indexed staff number derived from VoiceName
enum
Put a double bar at the end of sections and a final bar at the end of the
piece.
TODO: you could put more than one layer per staff if you wanted a 2-staff choirstaff (e.g., SA on one, TB on the other)
chorus2mei :: Arca -> (ListPosition, MusicChorus) -> String Source #
Take a list of sections, one per SATB voice, and create a single MEI
section
including all the voices.
Add a final bar at the end.
meiKey :: Tone -> ToneSystem -> String Source #
Create an MEI key signature (all naturals or one flat) based on tone
(key.sig
attribute for use in scoreDef
/staffDef
)
meiKeyAttr :: Tone -> ToneSystem -> String Source #
MEI key signature as an attribute (for use in staffDef
)
meiKeySigString :: Tone -> ToneSystem -> String Source #
Value for MEI key.sig
: one flat if tone is mollis, no signature
otherwise
meiMeter :: MusicMeter -> String Source #
Switch to select which kind of meter to use as an element
meiMeterAttr :: MusicMeter -> String Source #
Switch to select which kind of meter to use as an attribute
meiMeterModern :: MusicMeter -> String Source #
Create an MEI meter signature (using modern equivalents of Kircher's C,
C3, cutC3).
(meterSig with
meter.count and
meter.unit attributes for use in
scoreDef/
staffDef@)
meiMeterMensural :: MusicMeter -> String Source #
meiMeterMensuralAttr :: MusicMeter -> String Source #
Mensural meter with proportion as a string of attributes (for use in
staffDef
, where the correct encoding also works with Verovio).
meiMidiTempo :: MusicMeter -> String Source #
MEI tempo
element for MIDI speed: quarter-note (semiminim) beats per
minute, different tempi for each mensuration
meiMidiBPM :: MusicMeter -> String Source #
MEI midi.bpm
attribute appropriate for each mensuration
This is how it should work, but Verovio does not accept a tempo element
within staff, so I do not know how to do a tempo change mid-piece.
chorus2list :: MusicChorus -> [MusicSection] Source #
Extract a simple list of MusicSentence
from the four members of a
MusicChorus
Write a whole score to MEI
score2mei :: Arca -> ArkMetadata -> MusicScore -> String Source #
Convert a whole MusicScore
to MEI XML.
Include meter and key of first section in top-level scoreDef
(TODO ?)
Pass on the position in the list to the next function down.
The full MEI document
MEI Barlines
meiDoubleBar :: String Source #
Make an MEI double barline
meiFinalBar :: String Source #
Make an MEI final barline
Make an MEI barLine
element
String constants for XML document
_xmlHeader :: [Char] Source #
Default XML header
_meiVersion :: [Char] Source #
MEI version number
_projectDesc :: [Char] Source #
MEI project description text
Arguments
:: Int | 1-indexed MIDI instrument number (e.g., 19 = Church Organ) |
-> String | MEI |
MEI element for MIDI instrument number (1-indexed)
_midiInstrument :: String Source #
MIDI instrument for playback
The template
Arguments
:: String | title |
-> String | poet/author of words |
-> String | XML string with |
-> String | XML string with |
-> String | XML string with |
-> String | XML string representing the |
-> String |
Plug in variables and musical content needed to boilerplate MEI document in all its baroque verbosity