lib/head_music/pitch.rb in head_music-0.5.3 vs lib/head_music/pitch.rb in head_music-0.5.4

- old
+ new

@@ -2,11 +2,11 @@ include Comparable attr_reader :spelling attr_reader :octave - delegate :letter, :letter_cycle, to: :spelling + delegate :letter_name, :letter_name_cycle, to: :spelling delegate :accidental, :sharp?, :flat?, to: :spelling delegate :pitch_class, to: :spelling delegate :semitones, to: :accidental, prefix: true, allow_nil: true delegate :smallest_interval_to, to: :pitch_class @@ -26,18 +26,18 @@ spelling = HeadMusic::Spelling.from_number(number) octave = (number.to_i / 12) - 1 fetch_or_create(spelling, octave) end - def self.from_number_and_letter(number, letter) - letter = HeadMusic::LetterName.get(letter) - natural_letter_pitch = get(HeadMusic::LetterName.get(letter).pitch_class) + def self.from_number_and_letter(number, letter_name) + letter_name = HeadMusic::LetterName.get(letter_name) + natural_letter_pitch = get(HeadMusic::LetterName.get(letter_name).pitch_class) natural_letter_pitch += 12 while (number - natural_letter_pitch.to_i).to_i >= 11 natural_letter_pitch = get(natural_letter_pitch) accidental_interval = natural_letter_pitch.smallest_interval_to(HeadMusic::PitchClass.get(number)) accidental = HeadMusic::Accidental.for_interval(accidental_interval) - spelling = HeadMusic::Spelling.fetch_or_create(letter, accidental) + spelling = HeadMusic::Spelling.fetch_or_create(letter_name, accidental) fetch_or_create(spelling, natural_letter_pitch.octave) end def self.fetch_or_create(spelling, octave) @pitches ||= {} @@ -55,11 +55,11 @@ def name [spelling, octave].join end def midi_note_number - (octave + 1) * 12 + letter.pitch_class.to_i + accidental_semitones.to_i + (octave + 1) * 12 + letter_name.pitch_class.to_i + accidental_semitones.to_i end alias_method :midi, :midi_note_number alias_method :number, :midi_note_number @@ -69,10 +69,14 @@ def to_i midi_note_number end + def natural + HeadMusic::Pitch.get(self.to_s.gsub(/[#b]/, '')) + end + def enharmonic?(other) self.midi_note_number == other.midi_note_number end def +(value) @@ -97,9 +101,21 @@ self.midi_note_number <=> other.midi_note_number end def scale(scale_type_name = nil) HeadMusic::Scale.get(self, scale_type_name) + end + + def natural_steps(num_steps) + target_letter_name = self.letter_name.steps(num_steps) + direction = num_steps >= 0 ? 1 : -1 + octaves_delta = (num_steps.abs / 7) * direction + if num_steps < 0 && target_letter_name.position > letter_name.position + octaves_delta -= 1 + elsif num_steps > 0 && target_letter_name.position < letter_name.position + octaves_delta += 1 + end + HeadMusic::Pitch.get([target_letter_name, octave + octaves_delta].join) end private_class_method :new end