Class: HeadMusic::LetterName

Inherits:
Object
  • Object
show all
Defined in:
lib/head_music/letter_name.rb

Overview

Music has seven lette names that are used to identify pitches and pitch classes.

Constant Summary collapse

NAMES =
%w[C D E F G A B].freeze
NATURAL_PITCH_CLASS_NUMBERS =
{
  "C" => 0,
  "D" => 2,
  "E" => 4,
  "F" => 5,
  "G" => 7,
  "A" => 9,
  "B" => 11
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name) ⇒ LetterName

Returns a new instance of LetterName.



45
46
47
# File 'lib/head_music/letter_name.rb', line 45

def initialize(name)
  @name = name
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



39
40
41
# File 'lib/head_music/letter_name.rb', line 39

def name
  @name
end

Class Method Details

.allObject



15
16
17
# File 'lib/head_music/letter_name.rb', line 15

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

.from_name(name) ⇒ Object



23
24
25
26
27
# File 'lib/head_music/letter_name.rb', line 23

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

.from_pitch_class(pitch_class) ⇒ Object



29
30
31
32
33
34
35
36
37
# File 'lib/head_music/letter_name.rb', line 29

def self.from_pitch_class(pitch_class)
  @letter_names ||= {}
  return nil if pitch_class.to_s == pitch_class

  pitch_class = pitch_class.to_i % 12
  name = NAMES.detect { |candidate| pitch_class == NATURAL_PITCH_CLASS_NUMBERS[candidate] }
  name ||= HeadMusic::PitchClass::SHARP_SPELLINGS[pitch_class].first
  @letter_names[name] ||= new(name) if NAMES.include?(name)
end

.get(identifier) ⇒ Object



19
20
21
# File 'lib/head_music/letter_name.rb', line 19

def self.get(identifier)
  from_name(identifier) || from_pitch_class(identifier)
end

Instance Method Details

#==(other) ⇒ Object



53
54
55
# File 'lib/head_music/letter_name.rb', line 53

def ==(other)
  to_s == other.to_s
end

#pitch_classObject



49
50
51
# File 'lib/head_music/letter_name.rb', line 49

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

#positionObject



57
58
59
# File 'lib/head_music/letter_name.rb', line 57

def position
  NAMES.index(to_s) + 1
end

#series_ascendingObject



81
82
83
84
85
86
87
# File 'lib/head_music/letter_name.rb', line 81

def series_ascending
  @series_ascending ||= begin
    series = NAMES
    series = series.rotate while series.first != to_s
    series
  end
end

#series_descendingObject



89
90
91
92
93
94
95
# File 'lib/head_music/letter_name.rb', line 89

def series_descending
  @series_descending ||= begin
    series = NAMES.reverse
    series = series.rotate while series.first != to_s
    series
  end
end

#steps_down(num) ⇒ Object



65
66
67
# File 'lib/head_music/letter_name.rb', line 65

def steps_down(num)
  HeadMusic::LetterName.get(series_descending[num % NAMES.length])
end

#steps_to(other, direction = :ascending) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
# File 'lib/head_music/letter_name.rb', line 69

def steps_to(other, direction = :ascending)
  other = HeadMusic::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

#steps_up(num) ⇒ Object



61
62
63
# File 'lib/head_music/letter_name.rb', line 61

def steps_up(num)
  HeadMusic::LetterName.get(series_ascending[num % NAMES.length])
end