Sha256: aef711445451635277c8fcf3a0e05dfe3d28d72eccd6c86d55975187f20520c2

Contents?: true

Size: 1.49 KB

Versions: 1

Compression:

Stored size: 1.49 KB

Contents

# A Spelling is a pitch class with a letter and an accidental

class HeadMusic::Spelling
  attr_reader :letter
  attr_reader :accidental
  attr_reader :pitch_class

  SPELLING_MATCHER = /^\s*([A-G])([b#]*)(\-?\d+)?\s*$/

  def self.get(identifier)
    @spellings ||= {}
    @spellings[identifier] ||= from_name(identifier) || from_number(identifier)
  end

  def self.from_name(name)
    return nil unless name == name.to_s
    match = name.to_s.match(SPELLING_MATCHER)
    if match
      letter_name, accidental_string, _octave = match.captures
      letter = HeadMusic::Letter.get(letter_name)
      new(letter, HeadMusic::Accidental.get(accidental_string)) if letter
    end
  end

  def self.from_number(number)
    return nil unless number == number.to_i
    pitch_class_number = number.to_i % 12
    letter = HeadMusic::Letter.from_pitch_class(pitch_class_number)
    if letter.pitch_class != pitch_class_number
      accidental = HeadMusic::Accidental.for_interval(pitch_class_number - letter.pitch_class.to_i)
    end
    new(letter, accidental)
  end

  def initialize(letter, accidental = nil)
    @letter = HeadMusic::Letter.get(letter.to_s)
    @accidental = HeadMusic::Accidental.get(accidental.to_s)
    accidental_semitones = @accidental ? @accidental.semitones : 0
    @pitch_class = HeadMusic::PitchClass.get(letter.pitch_class + accidental_semitones)
  end

  def name
    [letter, accidental].join
  end

  def to_s
    name
  end

  def ==(value)
    to_s == value.to_s
  end

  private_class_method :new
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
head_music-0.1.1 lib/head_music/spelling.rb