arca- A digital implementation of Athanasius Kircher's device for automatic music composition, the Arca musarithmica of 1650

Copyright(c) 2022 Andrew A. Cashner
Safe HaskellNone




This module provides functions to adjust music created by the ark to follow conventions of musica ficta.


Adjust accidentals of individual pitches

changeNotePitch :: Note -> Pitch -> Note Source #

Copy a Note but change the Pitch

adjustNotePitch :: (Pitch -> Pitch) -> Note -> Note Source #

Copy a Note but adjust just its Pitch according to a function.

accidentalShift :: Pitch -> Accid -> Pitch Source #

Adjust the accidental either toward flats or toward sharps, within the Accid enum. If the accidental is unset we just return the original pitch. We are treating all accidental shifts as musica ficta and giving a Suggested accidType.

flatten :: Pitch -> Pitch Source #

Lower a pitch a semitone

sharpen :: Pitch -> Pitch Source #

Raise a pitch a semitone

changeAccid :: Accid -> AccidType -> Pitch -> Pitch Source #

Copy pitch but change accid and accidType

changeNoteAccid :: Accid -> AccidType -> Note -> Note Source #

Change the Accid of the Pitch within a Note

cancel :: Pitch -> Pitch Source #

Cancel an accidental (suggested)

noteCancel :: Note -> Note Source #

Cancel the Pitch within a Note.

Utilities to adjust pitches by MusicSection

adjustNotesInSection :: ([Note] -> [Note]) -> MusicSection -> MusicSection Source #

Do something to the Notes in every MusicPhrase within a MusicSection

changeNotesInPhrase :: MusicPhrase -> [Note] -> MusicPhrase Source #

Copy a MusicPhrase but with new notes

adjustNotesInPhrase :: ([Note] -> [Note]) -> MusicPhrase -> MusicPhrase Source #

Do something to the Note list in a MusicPhrase

fixFictaInSection Source #


:: ([Note] -> Note -> [Note])

fold function (arguments: stack and new item)

-> MusicSection 
-> MusicSection 

Fold a ficta-adjusting function over a MusicSection

fixFictaInPhrase Source #


:: ([Note] -> Note -> [Note])

fold function (arguments: stack and new item)

-> MusicPhrase 
-> MusicPhrase 

Fold a ficta-adjusting function over a MusicPhrase

foldStack Source #


:: ([a] -> a -> [a])

fold function (arguments: stack and new item)

-> [a] -> [a] 

Generate a stack folding function to process a list

adjustPhrasesRelative Source #


:: (MusicPhrase -> MusicPhrase -> MusicPhrase)

phrase transform function

-> MusicSection

lower voice section

-> MusicSection

upper voice section

-> MusicSection 

Map a function to the phrases in one section (upper voice) relative to the phrases in another section (lower voice).

findCounterpoint Source #


:: MusicPhrase

phrase to search for counterpoint

-> MusicPhrase

phrase containing the point to match up in the other voice

-> Int

index of point in its phrase

-> Note 

Compare two MusicPhrases and find the note in the one (lower) voice that coincides rhythmically with a given note in the other (upper) voice. Used to find harmonies and test them for bad intervals.

We find the top note by index and add the durations up to that point, then we add the durations in the bottom voice up to each item (that is, a scan) and then stop at the first item that matches the elapsed duration of the top voice.

durQuantity :: Dur -> Int Source #

What is the elapsed time of a Dur in units where Fs (fusa) = 1?

adjustFictaChorus :: ToneSystem -> ToneList -> MusicChorus -> MusicChorus Source #

Apply ficta adjustments to whole MusicPhrases. Adjust bass voice first; then adjust the upper voices individually, then adjust them again relative to the bass.

TODO nowhere do we deal with toneB (needed in s2/p4 for every 3rd and 4th line)

adjustFictaVoice :: ToneList -> Tone -> MusicSection -> MusicSection Source #

Adjust musica ficta for all the notes for one voice in a 'MusicSection.'

These rules are based on Kircher but had to be expanded as he doesn't account for some important and common cases.

TODO they still don't deal with every problem. Some would be automatically corrected by competent performers.

fix "illicit intervals" in the bass (p. 71)

#^7: (p. 69-70) - If the tone table has 8, keep the sharp - If it has #^7 and it is the last note in the phrase, and it is not the bass voice, keep the sharp - Otherwise make it natural

b^6: - If the tone table has b^6, cancel the flat if the next note is #^7

After making either of the above adjustments, go through and check for repeated notes: make them match the next accidental (G♮-G# should be G).

pitchClass :: Note -> Pnum Source #

Pitch class of Note

checkPnumAccid :: Pnum -> Accid -> Note -> Bool Source #

Test pitch class and accidental of Note

adjustRelBass Source #


:: ToneList 
-> Tone 
-> MusicSection

lower voice to compare

-> MusicSection

upper voice to adjust

-> MusicSection 

Adjust musica ficta in an upper voice relative to the bass. Avoid cross relations, augmented fifths, and certain tritones. (TODO which tritones?)

adjustRelUpper Source #


:: MusicSection

upper voice to compare

-> MusicSection

lower voice to adjust

-> MusicSection 

Adjust the Notes in a MusicSection relative to the voice above: avoid cross-relations between upper voices; where voices disagree, favor the upper voice.

Specific adjustments by rule

scaleDegree :: ToneList -> Tone -> Pitch -> Int Source #

Return the 0-indexed scale degree of a given pitch in a given tone (scale degree 0 is the modal final)

scaleDegree1 :: ToneList -> Tone -> Pitch -> Int Source #

1-indexed scale degree (more intelligible to the musical programmer)

isFictaAccid :: Accid -> Pitch -> Bool Source #

Does this Pitch have the given accidental as Suggested?

isCrossRelation :: Pitch -> Pitch -> Bool Source #

Are these pitches the same pitch class but different accidentals? (E.g., F vs F#?)

isAugFifth Source #


:: Pitch

lower pitch

-> Pitch

higher pitch

-> Bool 

Are these pitches an augmented fifth apart?

isTritone :: Pitch -> Pitch -> Bool Source #

Is this a tritone (diminished fifth or augmented fourth?)

isTritoneNote :: Note -> Note -> Bool Source #

Is the interval between these Notes a tritone?