about summary refs log tree commit diff
path: root/website/sandbox/chord-drill-sergeant/src/Theory.elm
diff options
context:
space:
mode:
authorWilliam Carroll <wpcarro@gmail.com>2020-04-13T09·02+0100
committerWilliam Carroll <wpcarro@gmail.com>2020-04-13T09·02+0100
commit774c0ddf05ebefc0a43fc80488267e313bfa6770 (patch)
tree1e206c96d9b6b1a001c73241fe9a78b64eda7be5 /website/sandbox/chord-drill-sergeant/src/Theory.elm
parentedc8f4ef6eaafd68c207e3fabd9fd588c4c50b62 (diff)
Rename NoteClass -> PitchClass
For the past two to three days, I've been searching for the name for the concept
of "C" or "A". From what I read, notes are specific things like C0 or C4, but I
wanted the name of the concept of a C. Thankfully today I discovered that this
is called a pitch class.
Diffstat (limited to 'website/sandbox/chord-drill-sergeant/src/Theory.elm')
-rw-r--r--website/sandbox/chord-drill-sergeant/src/Theory.elm253
1 files changed, 128 insertions, 125 deletions
diff --git a/website/sandbox/chord-drill-sergeant/src/Theory.elm b/website/sandbox/chord-drill-sergeant/src/Theory.elm
index ba95215a8cd1..63cba0e317af 100644
--- a/website/sandbox/chord-drill-sergeant/src/Theory.elm
+++ b/website/sandbox/chord-drill-sergeant/src/Theory.elm
@@ -110,7 +110,7 @@ type Note
 {-| I alluded to this concept in the Note type's documentation. These are the
 letters of notes. For instance C2, C3, C4 are all instances of C.
 -}
-type NoteClass
+type PitchClass
     = C
     | C_sharp
     | D
@@ -205,7 +205,7 @@ type KeyClass
 chords that harmonize with one another.
 -}
 type alias Key =
-    { noteClass : NoteClass
+    { pitchClass : PitchClass
     , mode : Mode
     }
 
@@ -225,24 +225,24 @@ type Mode
 type alias NoteMetadata =
     { note : Note
     , label : String
-    , noteClass : NoteClass
+    , pitchClass : PitchClass
     , natural : Bool
     }
 
 
-scaleDegree : Int -> Key -> NoteClass
-scaleDegree which { noteClass } =
-    case noteClass of
+scaleDegree : Int -> Key -> PitchClass
+scaleDegree which { pitchClass } =
+    case pitchClass of
         _ ->
             C
 
 
 {-| Returns the Note in the cental octave of the piano for a given
-NoteClass. For example, C4 -- or "middle C" -- for C.
+PitchClass. For example, C4 -- or "middle C" -- for C.
 -}
-noteInCentralOctave : NoteClass -> Note
-noteInCentralOctave noteClass =
-    case noteClass of
+noteInCentralOctave : PitchClass -> Note
+noteInCentralOctave pitchClass =
+    case pitchClass of
         C ->
             C4
 
@@ -543,7 +543,7 @@ step { direction, interval } note =
                 { direction = direction
                 , interval = Half
                 }
-                |> (\x -> applySteps x note)
+                |> (\x -> walkNotes x note)
                 |> Maybe.andThen (List.reverse >> List.head)
 
         Whole ->
@@ -598,13 +598,15 @@ In the case where applying any of the steps would result in running off of
 either edge of the piano, this function returns a Nothing.
 
 -}
-applySteps : List IntervalVector -> Note -> Maybe (List Note)
-applySteps steps note =
-    doApplySteps steps note [] |> Maybe.map List.reverse
+walkNotes : List IntervalVector -> Note -> Maybe (List Note)
+walkNotes steps note =
+    doWalkNotes steps note [] |> Maybe.map List.reverse
 
 
-doApplySteps : List IntervalVector -> Note -> List Note -> Maybe (List Note)
-doApplySteps steps note result =
+{-| Recursive helper for `walkNotes`.
+-}
+doWalkNotes : List IntervalVector -> Note -> List Note -> Maybe (List Note)
+doWalkNotes steps note result =
     case steps of
         [] ->
             Just (note :: result)
@@ -612,7 +614,7 @@ doApplySteps steps note result =
         s :: rest ->
             case step s note of
                 Just x ->
-                    doApplySteps rest x (note :: result)
+                    doWalkNotes rest x (note :: result)
 
                 Nothing ->
                     Nothing
@@ -629,11 +631,11 @@ keyClass note =
         Accidental
 
 
-{-| Return the NoteClass for a given note.
+{-| Return the PitchClass for a given note.
 -}
-classifyNote : Note -> NoteClass
+classifyNote : Note -> PitchClass
 classifyNote note =
-    note |> getNoteMetadata |> .noteClass
+    note |> getNoteMetadata |> .pitchClass
 
 
 {-| Return a list of the notes that comprise a `chord`
@@ -649,12 +651,12 @@ notesForChord { note, chordType, chordInversion } =
 {-| Return the scale for a given `key`
 -}
 notesForKey : Key -> List Note
-notesForKey { noteClass, mode } =
+notesForKey { pitchClass, mode } =
     let
         origin =
-            noteInCentralOctave noteClass
+            noteInCentralOctave pitchClass
     in
-    case applySteps (intervalsForMode mode) origin of
+    case walkNotes (intervalsForMode mode) origin of
         -- We should never hit the Nothing case here.
         Nothing ->
             []
@@ -716,94 +718,98 @@ allChordTypes =
     ]
 
 
+{-| Return an array of every note on a piano.
+Note: Currently this piano has 85 keys, but modern pianos have 88 keys. I would
+prefer to have 88 keys, but it's not urgent.
+-}
 noteMetadata : Array NoteMetadata
 noteMetadata =
     Array.fromList
-        [ { note = A1, label = "A1", noteClass = A, natural = True }
-        , { note = A_sharp1, label = "A♯/B♭1", noteClass = A_sharp, natural = False }
-        , { note = B1, label = "B1", noteClass = B, natural = True }
-        , { note = C1, label = "C1", noteClass = C, natural = True }
-        , { note = C_sharp1, label = "C♯/D♭1", noteClass = C_sharp, natural = False }
-        , { note = D1, label = "D1", noteClass = D, natural = True }
-        , { note = D_sharp1, label = "D♯/E♭1", noteClass = D_sharp, natural = False }
-        , { note = E1, label = "E1", noteClass = E, natural = True }
-        , { note = F1, label = "F1", noteClass = F, natural = True }
-        , { note = F_sharp1, label = "F♯/G♭1", noteClass = F_sharp, natural = False }
-        , { note = G1, label = "G1", noteClass = G, natural = True }
-        , { note = G_sharp1, label = "G♯/A♭1", noteClass = G, natural = False }
-        , { note = A2, label = "A2", noteClass = A, natural = True }
-        , { note = A_sharp2, label = "A♯/B♭2", noteClass = A_sharp, natural = False }
-        , { note = B2, label = "B2", noteClass = B, natural = True }
-        , { note = C2, label = "C2", noteClass = C, natural = True }
-        , { note = C_sharp2, label = "C♯/D♭2", noteClass = C_sharp, natural = False }
-        , { note = D2, label = "D2", noteClass = D, natural = True }
-        , { note = D_sharp2, label = "D♯/E♭2", noteClass = D_sharp, natural = False }
-        , { note = E2, label = "E2", noteClass = E, natural = True }
-        , { note = F2, label = "F2", noteClass = F, natural = True }
-        , { note = F_sharp2, label = "F♯/G♭2", noteClass = F_sharp, natural = False }
-        , { note = G2, label = "G2", noteClass = G, natural = True }
-        , { note = G_sharp2, label = "G♯/A♭2", noteClass = G, natural = False }
-        , { note = A3, label = "A3", noteClass = A, natural = True }
-        , { note = A_sharp3, label = "A♯/B♭3", noteClass = A_sharp, natural = False }
-        , { note = B3, label = "B3", noteClass = B, natural = True }
-        , { note = C3, label = "C3", noteClass = C, natural = True }
-        , { note = C_sharp3, label = "C♯/D♭3", noteClass = C_sharp, natural = False }
-        , { note = D3, label = "D3", noteClass = D, natural = True }
-        , { note = D_sharp3, label = "D♯/E♭3", noteClass = D_sharp, natural = False }
-        , { note = E3, label = "E3", noteClass = E, natural = True }
-        , { note = F3, label = "F3", noteClass = F, natural = True }
-        , { note = F_sharp3, label = "F♯/G♭3", noteClass = F_sharp, natural = False }
-        , { note = G3, label = "G3", noteClass = G, natural = True }
-        , { note = G_sharp3, label = "G♯/A♭3", noteClass = G, natural = False }
-        , { note = A4, label = "A4", noteClass = A, natural = True }
-        , { note = A_sharp4, label = "A♯/B♭4", noteClass = A_sharp, natural = False }
-        , { note = B4, label = "B4", noteClass = B, natural = True }
-        , { note = C4, label = "C4", noteClass = C, natural = True }
-        , { note = C_sharp4, label = "C♯/D♭4", noteClass = C_sharp, natural = False }
-        , { note = D4, label = "D4", noteClass = D, natural = True }
-        , { note = D_sharp4, label = "D♯/E♭4", noteClass = D_sharp, natural = False }
-        , { note = E4, label = "E4", noteClass = E, natural = True }
-        , { note = F4, label = "F4", noteClass = F, natural = True }
-        , { note = F_sharp4, label = "F♯/G♭4", noteClass = F_sharp, natural = False }
-        , { note = G4, label = "G4", noteClass = G, natural = True }
-        , { note = G_sharp4, label = "G♯/A♭4", noteClass = G, natural = False }
-        , { note = A5, label = "A5", noteClass = A, natural = True }
-        , { note = A_sharp5, label = "A♯/B♭5", noteClass = A_sharp, natural = False }
-        , { note = B5, label = "B5", noteClass = B, natural = True }
-        , { note = C5, label = "C5", noteClass = C, natural = True }
-        , { note = C_sharp5, label = "C♯/D♭5", noteClass = C_sharp, natural = False }
-        , { note = D5, label = "D5", noteClass = D, natural = True }
-        , { note = D_sharp5, label = "D♯/E♭5", noteClass = D_sharp, natural = False }
-        , { note = E5, label = "E5", noteClass = E, natural = True }
-        , { note = F5, label = "F5", noteClass = F, natural = True }
-        , { note = F_sharp5, label = "F♯/G♭5", noteClass = F_sharp, natural = False }
-        , { note = G5, label = "G5", noteClass = G, natural = True }
-        , { note = G_sharp5, label = "G♯/A♭5", noteClass = G, natural = False }
-        , { note = A6, label = "A6", noteClass = A, natural = True }
-        , { note = A_sharp6, label = "A♯/B♭6", noteClass = A_sharp, natural = False }
-        , { note = B6, label = "B6", noteClass = B, natural = True }
-        , { note = C6, label = "C6", noteClass = C, natural = True }
-        , { note = C_sharp6, label = "C♯/D♭6", noteClass = C_sharp, natural = False }
-        , { note = D6, label = "D6", noteClass = D, natural = True }
-        , { note = D_sharp6, label = "D♯/E♭6", noteClass = D_sharp, natural = False }
-        , { note = E6, label = "E6", noteClass = E, natural = True }
-        , { note = F6, label = "F6", noteClass = F, natural = True }
-        , { note = F_sharp6, label = "F♯/G♭6", noteClass = F_sharp, natural = False }
-        , { note = G6, label = "G6", noteClass = G, natural = True }
-        , { note = G_sharp6, label = "G♯/A♭6", noteClass = G, natural = False }
-        , { note = A7, label = "A7", noteClass = A, natural = True }
-        , { note = A_sharp7, label = "A♯/B♭7", noteClass = A_sharp, natural = False }
-        , { note = B7, label = "B7", noteClass = B, natural = True }
-        , { note = C7, label = "C7", noteClass = C, natural = True }
-        , { note = C_sharp7, label = "C♯/D♭7", noteClass = C_sharp, natural = False }
-        , { note = D7, label = "D7", noteClass = D, natural = True }
-        , { note = D_sharp7, label = "D♯/E♭7", noteClass = D_sharp, natural = False }
-        , { note = E7, label = "E7", noteClass = E, natural = True }
-        , { note = F7, label = "F7", noteClass = F, natural = True }
-        , { note = F_sharp7, label = "F♯/G♭7", noteClass = F_sharp, natural = False }
-        , { note = G7, label = "G7", noteClass = G, natural = True }
-        , { note = G_sharp7, label = "G♯/A♭7", noteClass = G, natural = False }
-        , { note = C8, label = "C8", noteClass = C, natural = True }
+        [ { note = A1, label = "A1", pitchClass = A, natural = True }
+        , { note = A_sharp1, label = "A♯/B♭1", pitchClass = A_sharp, natural = False }
+        , { note = B1, label = "B1", pitchClass = B, natural = True }
+        , { note = C1, label = "C1", pitchClass = C, natural = True }
+        , { note = C_sharp1, label = "C♯/D♭1", pitchClass = C_sharp, natural = False }
+        , { note = D1, label = "D1", pitchClass = D, natural = True }
+        , { note = D_sharp1, label = "D♯/E♭1", pitchClass = D_sharp, natural = False }
+        , { note = E1, label = "E1", pitchClass = E, natural = True }
+        , { note = F1, label = "F1", pitchClass = F, natural = True }
+        , { note = F_sharp1, label = "F♯/G♭1", pitchClass = F_sharp, natural = False }
+        , { note = G1, label = "G1", pitchClass = G, natural = True }
+        , { note = G_sharp1, label = "G♯/A♭1", pitchClass = G, natural = False }
+        , { note = A2, label = "A2", pitchClass = A, natural = True }
+        , { note = A_sharp2, label = "A♯/B♭2", pitchClass = A_sharp, natural = False }
+        , { note = B2, label = "B2", pitchClass = B, natural = True }
+        , { note = C2, label = "C2", pitchClass = C, natural = True }
+        , { note = C_sharp2, label = "C♯/D♭2", pitchClass = C_sharp, natural = False }
+        , { note = D2, label = "D2", pitchClass = D, natural = True }
+        , { note = D_sharp2, label = "D♯/E♭2", pitchClass = D_sharp, natural = False }
+        , { note = E2, label = "E2", pitchClass = E, natural = True }
+        , { note = F2, label = "F2", pitchClass = F, natural = True }
+        , { note = F_sharp2, label = "F♯/G♭2", pitchClass = F_sharp, natural = False }
+        , { note = G2, label = "G2", pitchClass = G, natural = True }
+        , { note = G_sharp2, label = "G♯/A♭2", pitchClass = G, natural = False }
+        , { note = A3, label = "A3", pitchClass = A, natural = True }
+        , { note = A_sharp3, label = "A♯/B♭3", pitchClass = A_sharp, natural = False }
+        , { note = B3, label = "B3", pitchClass = B, natural = True }
+        , { note = C3, label = "C3", pitchClass = C, natural = True }
+        , { note = C_sharp3, label = "C♯/D♭3", pitchClass = C_sharp, natural = False }
+        , { note = D3, label = "D3", pitchClass = D, natural = True }
+        , { note = D_sharp3, label = "D♯/E♭3", pitchClass = D_sharp, natural = False }
+        , { note = E3, label = "E3", pitchClass = E, natural = True }
+        , { note = F3, label = "F3", pitchClass = F, natural = True }
+        , { note = F_sharp3, label = "F♯/G♭3", pitchClass = F_sharp, natural = False }
+        , { note = G3, label = "G3", pitchClass = G, natural = True }
+        , { note = G_sharp3, label = "G♯/A♭3", pitchClass = G, natural = False }
+        , { note = A4, label = "A4", pitchClass = A, natural = True }
+        , { note = A_sharp4, label = "A♯/B♭4", pitchClass = A_sharp, natural = False }
+        , { note = B4, label = "B4", pitchClass = B, natural = True }
+        , { note = C4, label = "C4", pitchClass = C, natural = True }
+        , { note = C_sharp4, label = "C♯/D♭4", pitchClass = C_sharp, natural = False }
+        , { note = D4, label = "D4", pitchClass = D, natural = True }
+        , { note = D_sharp4, label = "D♯/E♭4", pitchClass = D_sharp, natural = False }
+        , { note = E4, label = "E4", pitchClass = E, natural = True }
+        , { note = F4, label = "F4", pitchClass = F, natural = True }
+        , { note = F_sharp4, label = "F♯/G♭4", pitchClass = F_sharp, natural = False }
+        , { note = G4, label = "G4", pitchClass = G, natural = True }
+        , { note = G_sharp4, label = "G♯/A♭4", pitchClass = G, natural = False }
+        , { note = A5, label = "A5", pitchClass = A, natural = True }
+        , { note = A_sharp5, label = "A♯/B♭5", pitchClass = A_sharp, natural = False }
+        , { note = B5, label = "B5", pitchClass = B, natural = True }
+        , { note = C5, label = "C5", pitchClass = C, natural = True }
+        , { note = C_sharp5, label = "C♯/D♭5", pitchClass = C_sharp, natural = False }
+        , { note = D5, label = "D5", pitchClass = D, natural = True }
+        , { note = D_sharp5, label = "D♯/E♭5", pitchClass = D_sharp, natural = False }
+        , { note = E5, label = "E5", pitchClass = E, natural = True }
+        , { note = F5, label = "F5", pitchClass = F, natural = True }
+        , { note = F_sharp5, label = "F♯/G♭5", pitchClass = F_sharp, natural = False }
+        , { note = G5, label = "G5", pitchClass = G, natural = True }
+        , { note = G_sharp5, label = "G♯/A♭5", pitchClass = G, natural = False }
+        , { note = A6, label = "A6", pitchClass = A, natural = True }
+        , { note = A_sharp6, label = "A♯/B♭6", pitchClass = A_sharp, natural = False }
+        , { note = B6, label = "B6", pitchClass = B, natural = True }
+        , { note = C6, label = "C6", pitchClass = C, natural = True }
+        , { note = C_sharp6, label = "C♯/D♭6", pitchClass = C_sharp, natural = False }
+        , { note = D6, label = "D6", pitchClass = D, natural = True }
+        , { note = D_sharp6, label = "D♯/E♭6", pitchClass = D_sharp, natural = False }
+        , { note = E6, label = "E6", pitchClass = E, natural = True }
+        , { note = F6, label = "F6", pitchClass = F, natural = True }
+        , { note = F_sharp6, label = "F♯/G♭6", pitchClass = F_sharp, natural = False }
+        , { note = G6, label = "G6", pitchClass = G, natural = True }
+        , { note = G_sharp6, label = "G♯/A♭6", pitchClass = G, natural = False }
+        , { note = A7, label = "A7", pitchClass = A, natural = True }
+        , { note = A_sharp7, label = "A♯/B♭7", pitchClass = A_sharp, natural = False }
+        , { note = B7, label = "B7", pitchClass = B, natural = True }
+        , { note = C7, label = "C7", pitchClass = C, natural = True }
+        , { note = C_sharp7, label = "C♯/D♭7", pitchClass = C_sharp, natural = False }
+        , { note = D7, label = "D7", pitchClass = D, natural = True }
+        , { note = D_sharp7, label = "D♯/E♭7", pitchClass = D_sharp, natural = False }
+        , { note = E7, label = "E7", pitchClass = E, natural = True }
+        , { note = F7, label = "F7", pitchClass = F, natural = True }
+        , { note = F_sharp7, label = "F♯/G♭7", pitchClass = F_sharp, natural = False }
+        , { note = G7, label = "G7", pitchClass = G, natural = True }
+        , { note = G_sharp7, label = "G♯/A♭7", pitchClass = G, natural = False }
+        , { note = C8, label = "C8", pitchClass = C, natural = True }
         ]
 
 
@@ -1106,10 +1112,10 @@ chordWithinRange start end chord =
             False
 
 
-{-| Return a list of all of the chords that we know about.
+{-| Return a list of all of the pitch classes that we know about.
 -}
-allNoteClasses : List NoteClass
-allNoteClasses =
+allPitchClasses : List PitchClass
+allPitchClasses =
     [ C
     , C_sharp
     , D
@@ -1134,14 +1140,14 @@ allChords :
     , end : Note
     , inversions : List ChordInversion
     , chordTypes : List ChordType
-    , noteClasses : List NoteClass
+    , pitchClasses : List PitchClass
     }
     -> List Chord
-allChords { start, end, inversions, chordTypes, noteClasses } =
+allChords { start, end, inversions, chordTypes, pitchClasses } =
     let
         notes =
             notesFromRange start end
-                |> List.filter (\note -> List.member (classifyNote note) noteClasses)
+                |> List.filter (\note -> List.member (classifyNote note) pitchClasses)
     in
     notes
         |> List.Extra.andThen
@@ -1163,28 +1169,25 @@ allChords { start, end, inversions, chordTypes, noteClasses } =
         |> List.filter (chordWithinRange start end)
 
 
-{-| Serialize a human-readable format of `note`.
+{-| Return a human-readable format of `note`.
 -}
 viewNote : Note -> String
 viewNote note =
     note |> getNoteMetadata |> .label
 
 
-inspectChord : Chord -> String
-inspectChord { note, chordType, chordInversion } =
-    viewNote note ++ " " ++ chordTypeName chordType ++ " " ++ inversionName chordInversion ++ " position"
-
-
+{-| Return a human-readable format of `chord`.
+-}
 viewChord : Chord -> String
 viewChord { note, chordType, chordInversion } =
-    viewNoteClass (classifyNote note) ++ " " ++ chordTypeName chordType ++ " " ++ inversionName chordInversion ++ " position"
+    viewPitchClass (classifyNote note) ++ " " ++ chordTypeName chordType ++ " " ++ inversionName chordInversion ++ " position"
 
 
-{-| Serialize a human-readable format of `noteClass`.
+{-| Return a human-readable format of `pitchClass`.
 -}
-viewNoteClass : NoteClass -> String
-viewNoteClass noteClass =
-    case noteClass of
+viewPitchClass : PitchClass -> String
+viewPitchClass pitchClass =
+    case pitchClass of
         C ->
             "C"