Skip to content

Instantly share code, notes, and snippets.

@cheebow
Created August 24, 2024 03:55
Show Gist options
  • Save cheebow/ddff7928803c0f233e7b580f663e13d8 to your computer and use it in GitHub Desktop.
Save cheebow/ddff7928803c0f233e7b580f663e13d8 to your computer and use it in GitHub Desktop.
ChordNotes
import Foundation
let noteToSemitone: [String: Int] = [
"C": 0, "C#": 1, "Db": 1,
"D": 2, "D#": 3, "Eb": 3,
"E": 4, "Fb": 4, "E#": 5,
"F": 5, "F#": 6, "Gb": 6,
"G": 7, "G#": 8, "Ab": 8,
"A": 9, "A#": 10, "Bb": 10,
"B": 11, "Cb": 11, "B#": 0
]
let semitoneToNote: [Int: (sharp: String, flat: String)] = [
0: ("C", "C"),
1: ("C#", "Db"),
2: ("D", "D"),
3: ("D#", "Eb"),
4: ("E", "Fb"),
5: ("F", "F"),
6: ("F#", "Gb"),
7: ("G", "G"),
8: ("G#", "Ab"),
9: ("A", "A"),
10: ("A#", "Bb"),
11: ("B", "Cb")
]
func chordNotes(chord: String) -> [String] {
let root = String(chord.prefix(while: { ["C", "D", "E", "F", "G", "A", "B"].contains($0) || $0 == "#" || $0 == "b" }))
let suffix = String(chord.dropFirst(root.count))
guard let rootSemitone = noteToSemitone[root] else {
return []
}
var intervals =
switch suffix {
case "m" : [0, 3, 7]
case "7" : [0, 4, 7, 10]
case "m7" : [0, 3, 7, 10]
case "M7" : [0, 4, 7, 11]
case "add9" : [0, 4, 7, 14]
case "madd9": [0, 3, 7, 14]
case "dim" : [0, 3, 6]
case "aug" : [0, 4, 8]
case "m7b5" : [0, 3, 6, 10]
default : [0, 4, 7]
}
let notes = intervals.map {
let semitone = ($0 + rootSemitone) % 12
return root.contains("#")
? semitoneToNote[semitone]!.sharp
: semitoneToNote[semitone]!.flat
}
return notes
}
// テスト例
let chord1 = "Cm7"
print("\(chord1): \(chordNotes(chord: chord1))")
let chord2 = "Fadd9"
print("\(chord2): \(chordNotes(chord: chord2))")
let chord3 = "F#m7b5"
print("\(chord3): \(chordNotes(chord: chord3))")
let chord4 = "AbM7"
print("\(chord4): \(chordNotes(chord: chord4))")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment