Skip to content

Commit

Permalink
rethinking how a note is handled
Browse files Browse the repository at this point in the history
  • Loading branch information
jwoertink committed Oct 21, 2016
1 parent ffdaa02 commit 884e909
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 47 deletions.
38 changes: 24 additions & 14 deletions spec/notes_spec.cr
Expand Up @@ -8,31 +8,41 @@ describe Medley::Notes do
note.halfstep_up.should eq "G#"
end

it "returns C when given B" do
it "returns B# when given B" do
note = Medley::Notes.new("B")
note.halfstep_up.should eq "C"
note.halfstep_up.should eq "B#"
end

it "returns E when given D#" do
it "returns D## when given D#" do
note = Medley::Notes.new("D#")
note.halfstep_up.should eq "E"
note.halfstep_up.should eq "D##"
end

it "returns B when given Bb" do
note = Medley::Notes.new("Bb")
note.halfstep_up.should eq "B"
end
end

describe ".wholestep_up" do
it "returns A when given G" do
note = Medley::Notes.new("G")
note.wholestep_up.should eq "A"
end

it "returns F for Eb" do
note = Medley::Notes.new("Eb")
note.wholestep_up.should eq "F"
it "returns F## when given E##" do
note = Medley::Notes.new("E##")
note.halfstep_up.should eq "F##"
end
end

#describe ".wholestep_up" do
# it "returns A when given G" do
# note = Medley::Notes.new("G")
# note.wholestep_up.should eq "A"
# end

# it "returns F for Eb" do
# note = Medley::Notes.new("Eb")
# note.wholestep_up.should eq "F"
# end

# it "returns F# for E" do
# note = Medley::Notes.new("E")
# note.wholestep_up.should eq "F#"
# end
#end
end
28 changes: 14 additions & 14 deletions spec/scales_spec.cr
Expand Up @@ -2,20 +2,20 @@ require "./spec_helper"

describe Medley::Scales do

describe ".notes" do
it "returns an array of letters in C major scale order" do
scale = Medley::Scales.new("Cmaj")
scale.notes.should eq(["C", "D", "E", "F", "G", "A", "B", "C"])
end
#describe ".notes" do
# it "returns an array of letters in C major scale order" do
# scale = Medley::Scales.new("Cmaj")
# scale.notes.should eq(["C", "D", "E", "F", "G", "A", "B", "C"])
# end

it "returns an array of letters in F major scale order" do
scale = Medley::Scales.new("Fmaj")
scale.notes.should eq(["F", "G", "A", "Bb", "C", "D", "E", "F"])
end
# it "returns an array of letters in F major scale order" do
# scale = Medley::Scales.new("Fmaj")
# scale.notes.should eq(["F", "G", "A", "Bb", "C", "D", "E", "F"])
# end

it "returns an array of letters in D Major scale order" do
scale = Medley::Scales.new("Dmaj")
scale.notes.should eq(["D", "E", "F#", "G", "A", "B", "C#", "D"])
end
end
# it "returns an array of letters in D Major scale order" do
# scale = Medley::Scales.new("Dmaj")
# scale.notes.should eq(["D", "E", "F#", "G", "A", "B", "C#", "D"])
# end
#end
end
62 changes: 43 additions & 19 deletions src/medley/notes.cr
@@ -1,46 +1,70 @@
module Medley
class Notes
NOTE_NAMES = %w(A B C D E F G)
ALIASES = {"B#": "C", "Cb": "B", "E#": "F", "Fb": "E",
"A#": "Bb", "Bb": "A#", "C#": "Db", "Db": "C#",
"D#": "Eb", "Eb": "D#", "F#": "Gb", "Gb": "F#"}

ALIASES = {"A##": "B", "B##": "C#", "C##": "D", "D##": "E",
"E##": "F#", "F##": "G", "G##": "A"}

def initialize(current_note : String)
@current_note = current_note
@previous_note = ""
end

def initialize(current_note : String, previous_note : String)
initialize(current_note)
@previous_note = previous_note
end

# true if it's a valid note letter with no modifiers
def natural?
NOTE_NAMES.includes?(@current_note)
!!name.match(/\A[A-G]\Z/)
end

# true if it's a valid note letter with b
def flat?
@current_note.includes?("b")
!!name.match(/\A[A-G]b\Z/)
end

# true if it's a valid note letter with bb
def double_flat?
!!name.match(/\A[A-G]bb\Z/)
end

# true if it's a valid note letter with #
def sharp?
@current_note.includes?("#")
!!name.match(/\A[A-G]#\Z/)
end

# true if it's a valid note letter with ##
def double_sharp?
!!name.match(/\A[A-G]##\Z/)
end

# Returns the current note name
def name
@current_note
end


# Returns the same note, but up a halfstep in most cases
# Without context of the Key, there's no telling if
# the note E should be E# or F. Since there's no triple sharps,
# this is the only case we just go to the next note.
def halfstep_up
if natural?
note = "#{@current_note}#"
return ALIASES[note]? || note
elsif sharp?
idx = NOTE_NAMES.index(@current_note[0].to_s) || -1
return NOTE_NAMES[idx + 1]? || NOTE_NAMES[0]
elsif flat?
@current_note[0].to_s
else
return NOTE_NAMES[0]
case self
when .natural?, .sharp?
return "#{@current_note}#"
when .flat?
return @current_note[0].to_s
when .double_flat?
@current_note[0..1].to_s
when .double_sharp?
puts "double sharp #{@current_note}"
aliased = ALIASES[@current_note]
return "#{aliased}#"
end
end

def wholestep_up
new_note = Medley::Notes.new(halfstep_up)
new_note = Medley::Notes.new(halfstep_up, @current_note)
new_note.halfstep_up
end
end
Expand Down
1 change: 1 addition & 0 deletions src/medley/scales.cr
Expand Up @@ -40,6 +40,7 @@ module Medley
if offending = @notes.find { |n| n[0] == new_note[0] && n.size > 1 }
new_note = Medley::Notes::ALIASES[new_note]
idx = @notes.index(offending)
return if idx.nil?
@notes[idx] = new_note
end
@notes << new_note
Expand Down

0 comments on commit 884e909

Please sign in to comment.