type NoteName
= C
| D
| E
| F
| G
| A
| B
renderNotes : List NoteName -> Html msg
renderNotes notes =
svg [...] [...]
Frey, P.W. & Adesman, P. Memory & Cognition (1976) 4: 541. https://doi.org/10.3758/BF03213216
noteNameToInt : NoteName -> Int
noteNameToInt note =
case note of
C -> 0
D -> 1
E -> 2
F -> 3
G -> 4
A -> 5
B -> 6
computeDistance : NoteName -> NoteName -> Int
computeDistance note1 note2 =
let
n1 = noteNameToInt note1
n2 = noteNameToInt note2
in
abs <| n1 - n2
type alias Note =
{ name : NoteName
, octave : Int
}
computeDistance : NoteName -> NoteName -> Int
computeDistance : Note -> Note -> Int
computeDistance note1 note2 =
let
n1 = noteNameToInt note1
n2 = noteNameToInt note2
n1 = noteNameToInt note1.name + (note1.octave * 7)
n2 = noteNameToInt note2.name + (note2.octave * 7)
in
abs <| n1 - n2
getBasicInterval : Note -> Int -> Note
getBasicInterval note interval =
...
middleC =
{ name : C
, octave : 4
}
interval = 3
getBasicInterval middleC interval == Note E 4
type Accidental
= Sharp
| None
| Flat
...
type alias Note =
{ name : NoteName
, accidental : Accidental
, octave : Int
}
type Quality
= Minor
| Major
...
noteNameToHalfStep : NoteName -> Int
noteNameToHalfStep note =
case note of
C -> 0
D -> 2
E -> 4
F -> 5
G -> 7
A -> 9
B -> 11
accidentalToHalfStep : Accidental -> Int
accidentalToHalfStep accidental =
case accidental of
Sharp -> 1
None -> 0
Flat -> -1
...
noteToHalfStep : Note -> Int
noteToHalfStep note =
noteNameToHalfStep note.name +
accidentalToHalfStep note.accidental +
note.octave * 12
computeInterval : Note -> Note -> (Quality, Int)
computeInterval note1 note2 =
let
halfSteps =
abs <| noteToHalfStep note1 - noteToHalfStep note2
letterDistance =
computeDistance note1 note2
in
case letterDistance + 1 of
3 ->
case halfSteps of
3 -> (Minor, letterDistance + 1)
4 -> (Major, letterDistance + 1)
...
case letterDistance + 1 of
case (modBy 7 letterDistance) + 1 of
3 ->
case halfSteps of
case modBy 12 halfSteps of
3 -> (Minor, letterDistance + 1)
4 -> (Major, letterDistance + 1)
getInterval : Note -> (Quality, Int) -> Note
getInterval note (quality, interval) =
...
middleC =
{ name : C
, accidental : None
, octave : 4
}
interval = (Minor, 3)
getInterval middleC interval == Note E Flat 4
getTriad : Note -> Quality -> List Note
getTriad root quality =
case quality of
Major ->
[ root
, getInterval root Major 3
, getInterval root Perfect 5
]
...