Skip to content

Instantly share code, notes, and snippets.

@aaronrenner
Created June 3, 2014 23:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aaronrenner/fd816206a30c4d42914c to your computer and use it in GitHub Desktop.
Save aaronrenner/fd816206a30c4d42914c to your computer and use it in GitHub Desktop.
Dodecaphony pitch class
class Pitch
attr_reader :name
VALID_PITCHES = {'A' => 0, 'B' => 2, 'C' => 3, 'D' => 5,
'E' => 7, 'F' => 8, 'G' => 10}
SHARP_NAMES = {
0 => 'A',
1 => 'A#',
2 => 'B',
3 => 'C',
4 => 'C#',
5 => 'D',
6 => 'D#',
7 => 'E',
8 => 'F',
9 => 'F#',
10 => 'G',
11 => 'G#',
}
FLAT_NAMES = {
0 => 'A',
1 => 'Bb',
2 => 'B',
3 => 'C',
4 => 'Db',
5 => 'D',
6 => 'Eb',
7 => 'E',
8 => 'F',
9 => 'Gb',
10 => 'G',
11 => 'Ab',
}
private_constant :VALID_PITCHES
def initialize pitch_name
self.name = pitch_name
validate_name
self.pitch_number = adjust_for_accidentals(starting_number)
end
def distance_from second_pitch
ensure_number_scale(second_pitch.pitch_number - pitch_number)
end
def spell_as_sharp
SHARP_NAMES[pitch_number]
end
def spell_as_flat
FLAT_NAMES[pitch_number]
end
protected
attr_reader :pitch_number
private
attr_writer :name, :pitch_number
def validate_name
unless VALID_PITCHES.has_key?(starting_letter)
raise ArgumentError, 'invalid pitch name'
end
end
def accidentals
name.downcase.split(//)[1..-1]
end
def adjust_for_accidentals number
accidentals.each do |a|
number += 1 if a == '+' or a == '#'
number -= 1 if a == '-' or a == 'b'
end
ensure_number_scale number
end
def ensure_number_scale number
number % 12
end
def starting_number
VALID_PITCHES[starting_letter]
end
def starting_letter
name.upcase.split(//)[0]
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment