Skip to content

Commit

Permalink
Add motifs including arpeggios (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
dpsanders authored Dec 31, 2023
1 parent 3e1f763 commit 5601ba4
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 0 deletions.
58 changes: 58 additions & 0 deletions src/motifs.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@

# A motif is a repeating pattern within a scale
# Specify by how many scale notes to increment for each subsequent note

arpeggio = [2, 2, 3]
# broken thirds = [2, -1]
# broken octaves = [7, -6]
# broken arpeggio = [4, -2, 5]

# stateful iterator:
mutable struct Motif
scale::Scale
pattern::Vector{Int}
current::Pitch
i::Int
end

Motif(scale, pattern) = Motif(scale, pattern, first(iterate(scale)), 1)

function Base.iterate(m::Motif)
return_value = m.current
current, next = iterate(scale)

for i in 1:m.pattern[m.i] - 1
current, next = iterate(scale, next)
end

m.i += 1
if m.i > length(m.pattern)
m.i = 1
end

m.current = return_value
return return_value, next
end

function Base.iterate(m::Motif, next)

return_value = next

for i in 1:m.pattern[m.i]
current, next = iterate(scale, next)
end

m.i += 1
if m.i > length(m.pattern)
m.i = 1
end

m.current = return_value

return return_value, next
end


Base.IteratorSize(::Type{Motif}) = Base.IsInfinite()
Base.IteratorEltype(::Type{Motif}) = Base.HasEltype()
Base.eltype(::Type{Motif}) = Pitch
8 changes: 8 additions & 0 deletions test/motifs.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@testset "Arpeggio" begin
scale = Scale(C[4], major_scale)
arpeggio_motif = Motif(scale, [2, 2, 3])

arpeggio = collect(Base.Iterators.take(arpeggio_motif, 6))

@test arpeggio == Pitch[C[4], E[4], G[4], C[5], E[5], G[5]]
end

0 comments on commit 5601ba4

Please sign in to comment.