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.



47
48
49
# File 'lib/head_music/letter_name.rb', line 47

def initialize(name)
  @name = name
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



41
42
43
# File 'lib/head_music/letter_name.rb', line 41

def name
  @name
end

Class Method Details

.allObject



17
18
19
# File 'lib/head_music/letter_name.rb', line 17

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

.from_name(name) ⇒ Object



25
26
27
28
29
# File 'lib/head_music/letter_name.rb', line 25

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



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

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



21
22
23
# File 'lib/head_music/letter_name.rb', line 21

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

Instance Method Details

#==(other) ⇒ Object



55
56
57
# File 'lib/head_music/letter_name.rb', line 55

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

#pitch_classObject



51
52
53
# File 'lib/head_music/letter_name.rb', line 51

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

#positionObject



59
60
61
# File 'lib/head_music/letter_name.rb', line 59

def position
  NAMES.index(to_s) + 1
end

#series_ascendingObject



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

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

#series_descendingObject



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

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

#steps_down(num) ⇒ Object



67
68
69
# File 'lib/head_music/letter_name.rb', line 67

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

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



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

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



63
64
65
# File 'lib/head_music/letter_name.rb', line 63

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