Skip to content

Commit

Permalink
Add triads and note names (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
dpsanders authored Dec 31, 2023
1 parent e386bc1 commit 3e1f763
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 20 deletions.
4 changes: 4 additions & 0 deletions src/MusicTheory.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@ export major_scale, natural_minor_scale, melodic_minor_scale, harmonic_minor_sca

export Chord

export make_triad, is_triad


include("notes.jl")
include("note_names.jl")
include("intervals.jl")
include("scales.jl")
include("chords.jl")
include("triads.jl")
end
12 changes: 12 additions & 0 deletions src/chords.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@


# const Chord{T <: Union{PitchClass, Pitch}} = Set{T}

struct Chord{T <: Union{PitchClass, Pitch}}
notes::Set{T}
end

Chord(notes::T...) where {T <: Union{PitchClass, Pitch}} = Chord{T}(Set(notes))


Base.length(chord::Chord) = length(chord.notes)
44 changes: 44 additions & 0 deletions src/note_names.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@

module NoteNames

using MusicTheory:
C, D, E, F, G, A, B,
C♮, D♮, E♮, F♮, G♮, A♮, B♮,
C♯, D♯, E♯, F♯, G♯, A♯, B♯,
C♭, D♭, E♭, F♭, G♭, A♭, B♭,
C𝄫, D𝄫, E𝄫, F𝄫, G𝄫, A𝄫, B𝄫,
C𝄪, D𝄪, E𝄪, F𝄪, G𝄪, A𝄪, B𝄪

export
C, D, E, F, G, A, B,
C♮, D♮, E♮, F♮, G♮, A♮, B♮,
C♯, D♯, E♯, F♯, G♯, A♯, B♯,
C♭, D♭, E♭, F♭, G♭, A♭, B♭,
C𝄫, D𝄫, E𝄫, F𝄫, G𝄫, A𝄫, B𝄫,
C𝄪, D𝄪, E𝄪, F𝄪, G𝄪, A𝄪, B𝄪,
middle_C

const middle_C = C[4]

end


module AllNoteNames

using MusicTheory: note_names, Pitch, PitchClass, Accidental

using MusicTheory.NoteNames

for note in note_names, octave in 0:9
name = Symbol(note, octave)
@eval $(name) = Pitch(PitchClass($(Meta.quot(note))), $(octave))
@eval export $(name)

for accidental in instances(Accidental)
name = Symbol(note, accidental, octave)
@eval $(name) = Pitch(PitchClass($(Meta.quot(note)), $(accidental)), $(octave))
@eval export $(name)
end
end

end
20 changes: 0 additions & 20 deletions src/notes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -83,24 +83,8 @@ Base.isless(n1::PitchClass, n2::PitchClass) = semitone(n1) < semitone(n2)
Base.isless(n1::Pitch, n2::Pitch) = semitone(n1) < semitone(n2)




# define Julia objects for pitch classes:

module NoteNames

using MusicTheory
using MusicTheory: note_names

export
C, D, E, F, G, A, B,
C♮, D♮, E♮, F♮, G♮, A♮, B♮,
C♯, D♯, E♯, F♯, G♯, A♯, B♯,
C♭, D♭, E♭, F♭, G♭, A♭, B♭,
C𝄫, D𝄫, E𝄫, F𝄫, G𝄫, A𝄫, B𝄫,
C𝄪, D𝄪, E𝄪, F𝄪, G𝄪, A𝄪, B𝄪,
middle_C

for name in note_names, accidental in instances(Accidental)
note = Symbol(name, accidental)

Expand All @@ -111,7 +95,3 @@ for name in note_names, accidental in instances(Accidental)
end
end

const middle_C = C[4]


end
42 changes: 42 additions & 0 deletions src/triads.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
function make_triad(scale::Scale, root::Pitch)

!haskey(scale.steps, PitchClass(root)) && error("$root not in scale")

triad_notes = [root]

current, next = iterate(scale, root)
current, next = iterate(scale, next)

push!(triad_notes, next)

current, next = iterate(scale, next)
current, next = iterate(scale, next)

push!(triad_notes, next)

return Chord(triad_notes...)
end


function find_intervals(chord)
notes = sort(collect(chord.notes))
# return [interval(n1, n2) for n1 in notes for n2 in notes if n1 < n2]
return [Interval(notes[1], notes[2]), Interval(notes[1], notes[3])]
end


function is_triad(chord::Chord{PitchClass})
length(chord) != 3 && return false

# put them in the same octave:
pitches = [Pitch(n, 4) for n in chord.notes]

intervals = find_intervals(Chord(pitches...)) |> collect
numbers = (intervals[1].number, intervals[2].number)

return numbers ( (3, 5), (3, 6), (4, 6) )
end

is_triad(chord::Chord{Pitch}) = is_triad(Chord(PitchClass.(chord.notes)...))

is_triad(notes...) = is_triad(Chord(notes...))
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ using Test
include("notes.jl")
include("intervals.jl")
include("scales.jl")
include("triads.jl")
13 changes: 13 additions & 0 deletions test/triads.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
@testset "Triads" begin
@test is_triad(Chord(B, D, F))
@test is_triad(B[4], D[7], F[1])

@test !is_triad(Chord(A, B, C))
@test !is_triad(A, B, C)
end

@testset "Triads with names" begin
using MusicTheory.AllNoteNames

@test is_triad(C4, E5, A8)
end

0 comments on commit 3e1f763

Please sign in to comment.