lib/head_music/scale.rb in head_music-0.3.0 vs lib/head_music/scale.rb in head_music-0.3.1
- old
+ new
@@ -15,35 +15,18 @@
@scale_type = HeadMusic::ScaleType.get(scale_type)
end
def pitches
@pitches ||= begin
- pitches = [root_pitch]
- letters_cycle = HeadMusic::Letter::NAMES
- letters_cycle = letters_cycle.rotate while letters_cycle.first != root_pitch.letter.to_s
+ letter_cycle = root_pitch.letter_cycle
semitones_from_root = 0
- if scale_type.parent
- parent_scale_pitches = HeadMusic::Scale.get(root_pitch, scale_type.parent_name).pitches
- end
- scale_type.intervals.each_with_index do |semitones, i|
- semitones_from_root += semitones
- pitch_number = root_pitch.pitch_class.to_i + semitones_from_root
- if scale_type.intervals.length == 7
- current_letter = letters_cycle[(i + 1) % 7]
- elsif scale_type.intervals.length < 7 && scale_type.parent
- current_letter = parent_scale_pitches.detect { |parent_scale_pitches|
- parent_scale_pitches.pitch_class == (root_pitch + semitones_from_root).to_i % 12
- }.letter
- elsif root_pitch.flat?
- current_letter = HeadMusic::PitchClass::FLAT_SPELLINGS[pitch_number % 12]
- else
- current_letter = HeadMusic::PitchClass::SHARP_SPELLINGS[pitch_number % 12]
+ [root_pitch].tap do |pitches|
+ scale_type.intervals.each_with_index do |semitones, i|
+ semitones_from_root += semitones
+ pitches << pitch_for_step(i+1, semitones_from_root)
end
- pitch = HeadMusic::Pitch.from_number_and_letter(pitch_number, current_letter)
- pitches << pitch
end
- pitches
end
end
def pitch_names
pitches.map(&:spelling).map(&:to_s)
@@ -62,7 +45,46 @@
spellings << HeadMusic::Spelling.get([letter, accidental].join)
end
letter_index = (letter_index + 1) % 7
end
spellings
+ end
+
+ def letter_cycle
+ @letter_cycle ||= root_pitch.letter_cycle
+ end
+
+ def root_pitch_class
+ @root_pitch_class ||= root_pitch.pitch_class
+ end
+
+ private
+
+ def parent_scale_pitches
+ HeadMusic::Scale.get(root_pitch, scale_type.parent_name).pitches if scale_type.parent
+ end
+
+ def parent_scale_pitch_for(semitones_from_root)
+ parent_scale_pitches.detect { |parent_scale_pitch|
+ parent_scale_pitch.pitch_class == (root_pitch + semitones_from_root).to_i % 12
+ }
+ end
+
+ def letter_for_step(step, semitones_from_root)
+ pitch_class_number = (root_pitch.pitch_class.to_i + semitones_from_root) % 12
+ if scale_type.intervals.length == 7
+ letter_cycle[step % 7]
+ elsif scale_type.intervals.length < 7 && parent_scale_pitches
+ parent_scale_pitch_for(semitones_from_root).letter
+ elsif root_pitch.flat?
+ HeadMusic::PitchClass::FLAT_SPELLINGS[pitch_class_number]
+ else
+ HeadMusic::PitchClass::SHARP_SPELLINGS[pitch_class_number]
+ end
+ end
+
+ def pitch_for_step(step, semitones_from_root)
+ pitch_number = root_pitch_class.to_i + semitones_from_root
+ letter = letter_for_step(step, semitones_from_root)
+ HeadMusic::Pitch.from_number_and_letter(pitch_number, letter)
end
end