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