Sha256: 393c96895e9746fafd84f1e9b4b9b9e4dae2c6ebb2d02b1f4a67d9b2c6722b2d

Contents?: true

Size: 1.86 KB

Versions: 1

Compression:

Stored size: 1.86 KB

Contents

class HeadMusic::LetterName
  # Defines the natural relationship between the natural letter-named notes

  NAMES = ('A'..'G').to_a

  NATURAL_PITCH_CLASS_NUMBERS = {
    'C' => 0,
    'D' => 2,
    'E' => 4,
    'F' => 5,
    'G' => 7,
    'A' => 9,
    'B' => 11,
  }

  def self.all
    NAMES.map { |letter_name| get(letter_name)}
  end

  def self.get(identifier)
    from_name(identifier) || from_pitch_class(identifier)
  end
  singleton_class.send(:alias_method, :[], :get)

  def self.from_name(name)
    @letters ||= {}
    name = name.to_s.first.upcase
    @letters[name] ||= new(name) if NAMES.include?(name)
  end

  def self.from_pitch_class(pitch_class)
    @letters ||= {}
    return nil if pitch_class.to_s == pitch_class
    pitch_class = pitch_class.to_i % 12
    name = NAMES.detect { |name| pitch_class == NATURAL_PITCH_CLASS_NUMBERS[name] }
    name ||= HeadMusic::PitchClass::PREFERRED_SPELLINGS[pitch_class].first
    @letters[name] ||= new(name) if NAMES.include?(name)
  end

  attr_reader :name

  delegate :to_s, to: :name
  delegate :to_sym, to: :name
  delegate :to_i, to: :pitch_class

  def initialize(name)
    @name = name
  end

  def pitch_class
    HeadMusic::PitchClass.get(NATURAL_PITCH_CLASS_NUMBERS[name])
  end

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

  def position
    NAMES.index(self.to_s) + 1
  end

  def steps(num)
    cycle[num]
  end

  def steps_to(other, direction = :ascending)
    other = LetterName.get(other)
    other_position = other.position
    if direction == :descending
      other_position -= NAMES.length if other_position > position
      position - other_position
    else
      other_position += NAMES.length if other_position < position
      other_position - position
    end
  end

  def cycle
    cycle = NAMES
    while cycle.first != self.to_s
      cycle = cycle.rotate
    end
    cycle
  end

  private_class_method :new
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
head_music-0.5.3 lib/head_music/letter_name.rb