Class: HeadMusic::Rudiment::KeySignature

Inherits:
Base
  • Object
show all
Defined in:
lib/head_music/rudiment/key_signature.rb

Overview

Represents a key signature (traditionally associated with a key) This class maintains backward compatibility while delegating to Key/Mode internally

Defined Under Namespace

Classes: EnharmonicEquivalence

Constant Summary collapse

ORDERED_LETTER_NAMES_OF_SHARPS =
%w[F C G D A E B].freeze
ORDERED_LETTER_NAMES_OF_FLATS =
ORDERED_LETTER_NAMES_OF_SHARPS.reverse.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(tonic_spelling, scale_type = nil) ⇒ KeySignature

Returns a new instance of KeySignature.



41
42
43
44
45
46
47
# File 'lib/head_music/rudiment/key_signature.rb', line 41

def initialize(tonic_spelling, scale_type = nil)
  @tonic_spelling = HeadMusic::Rudiment::Spelling.get(tonic_spelling)
  @scale_type = HeadMusic::Rudiment::ScaleType.get(scale_type) if scale_type
  @scale_type ||= HeadMusic::Rudiment::ScaleType.default
  @scale_type = @scale_type.parent || @scale_type
  @scale = HeadMusic::Rudiment::Scale.get(@tonic_spelling, @scale_type)
end

Instance Attribute Details

#scaleObject (readonly)

Returns the value of attribute scale.



35
36
37
# File 'lib/head_music/rudiment/key_signature.rb', line 35

def scale
  @scale
end

#scale_typeObject (readonly)

Returns the value of attribute scale_type.



35
36
37
# File 'lib/head_music/rudiment/key_signature.rb', line 35

def scale_type
  @scale_type
end

#tonic_spellingObject (readonly)

Returns the value of attribute tonic_spelling.



35
36
37
# File 'lib/head_music/rudiment/key_signature.rb', line 35

def tonic_spelling
  @tonic_spelling
end

Class Method Details

.defaultObject



10
11
12
# File 'lib/head_music/rudiment/key_signature.rb', line 10

def self.default
  @default ||= new("C", :major)
end

.from_scale(scale) ⇒ Object



28
29
30
31
32
33
# File 'lib/head_music/rudiment/key_signature.rb', line 28

def self.from_scale(scale)
  # Find a key or mode that uses this scale
  tonic = scale.root_pitch.spelling
  scale_type = scale.scale_type
  new(tonic, scale_type)
end

.get(identifier) ⇒ Object



14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/head_music/rudiment/key_signature.rb', line 14

def self.get(identifier)
  return identifier if identifier.is_a?(HeadMusic::Rudiment::KeySignature)

  @key_signatures ||= {}

  if identifier.is_a?(String)
    tonic_spelling, scale_type_name = identifier.strip.split(/\s/)
    hash_key = HeadMusic::Utilities::HashKey.for(identifier.gsub(/#|♯/, " sharp").gsub(/(\w)[b♭]/, '\\1 flat'))
    @key_signatures[hash_key] ||= new(tonic_spelling, scale_type_name)
  elsif identifier.is_a?(HeadMusic::Rudiment::DiatonicContext)
    identifier.key_signature
  end
end

Instance Method Details

#==(other) ⇒ Object



92
93
94
# File 'lib/head_music/rudiment/key_signature.rb', line 92

def ==(other)
  alterations == self.class.get(other).alterations
end

#alterationsObject Also known as: sharps_and_flats, accidentals



81
82
83
# File 'lib/head_music/rudiment/key_signature.rb', line 81

def alterations
  flats.any? ? (double_flats + flats) : (double_sharps + sharps)
end

#altered_spellings(predicate, letter_name_order) ⇒ Object (private)



109
110
111
112
113
# File 'lib/head_music/rudiment/key_signature.rb', line 109

def altered_spellings(predicate, letter_name_order)
  spellings.select(&predicate).sort_by do |spelling|
    letter_name_order.index(spelling.letter_name.to_s)
  end
end

#double_flatsObject



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

def double_flats
  altered_spellings(:double_flat?, ORDERED_LETTER_NAMES_OF_FLATS)
end

#double_sharpsObject



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

def double_sharps
  altered_spellings(:double_sharp?, ORDERED_LETTER_NAMES_OF_SHARPS)
end

#enharmonic_equivalenceObject (private)



119
120
121
# File 'lib/head_music/rudiment/key_signature.rb', line 119

def enharmonic_equivalence
  @enharmonic_equivalence ||= HeadMusic::Rudiment::KeySignature::EnharmonicEquivalence.get(self)
end

#enharmonic_equivalent?(other) ⇒ Boolean

Returns:

  • (Boolean)


103
104
105
# File 'lib/head_music/rudiment/key_signature.rb', line 103

def enharmonic_equivalent?(other)
  enharmonic_equivalence.enharmonic_equivalent?(other)
end

#flatsObject



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

def flats
  altered_spellings(:flat?, ORDERED_LETTER_NAMES_OF_FLATS)
end

#nameObject



88
89
90
# File 'lib/head_music/rudiment/key_signature.rb', line 88

def name
  [tonic_spelling, scale_type].join(" ")
end

#num_alterationsObject



77
78
79
# File 'lib/head_music/rudiment/key_signature.rb', line 77

def num_alterations
  num_sharps + num_flats
end

#num_flatsObject



73
74
75
# File 'lib/head_music/rudiment/key_signature.rb', line 73

def num_flats
  flats.length + double_flats.length * 2
end

#num_sharpsObject



69
70
71
# File 'lib/head_music/rudiment/key_signature.rb', line 69

def num_sharps
  sharps.length + double_sharps.length * 2
end

#pluralize(count, noun) ⇒ Object (private)



115
116
117
# File 'lib/head_music/rudiment/key_signature.rb', line 115

def pluralize(count, noun)
  (count == 1) ? "1 #{noun}" : "#{count} #{noun}s"
end

#sharpsObject



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

def sharps
  altered_spellings(:sharp?, ORDERED_LETTER_NAMES_OF_SHARPS)
end

#spellingsObject



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

def spellings
  pitches.map(&:spelling).uniq
end

#to_sObject



96
97
98
99
100
101
# File 'lib/head_music/rudiment/key_signature.rb', line 96

def to_s
  return pluralize(sharps.length, "sharp") if sharps.any?
  return pluralize(flats.length, "flat") if flats.any?

  "no sharps or flats"
end