Class: HeadMusic::KeySignature

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

Overview

Represents a key signature.

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.



25
26
27
28
29
30
31
# File 'lib/head_music/key_signature.rb', line 25

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

Instance Attribute Details

#scaleObject (readonly)

Returns the value of attribute scale.



3
4
5
# File 'lib/head_music/key_signature.rb', line 3

def scale
  @scale
end

#scale_typeObject (readonly)

Returns the value of attribute scale_type.



3
4
5
# File 'lib/head_music/key_signature.rb', line 3

def scale_type
  @scale_type
end

#tonic_spellingObject (readonly)

Returns the value of attribute tonic_spelling.



3
4
5
# File 'lib/head_music/key_signature.rb', line 3

def tonic_spelling
  @tonic_spelling
end

Class Method Details

.defaultObject



8
9
10
# File 'lib/head_music/key_signature.rb', line 8

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

.get(identifier) ⇒ Object



12
13
14
15
16
17
18
19
# File 'lib/head_music/key_signature.rb', line 12

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

  @key_signatures ||= {}
  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)
end

Instance Method Details

#==(other) ⇒ Object



84
85
86
# File 'lib/head_music/key_signature.rb', line 84

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

#alterationsObject Also known as: sharps_and_flats, accidentals



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

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

#double_flatsObject



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

def double_flats
  spellings.select(&:double_flat?).sort_by do |spelling|
    ORDERED_LETTER_NAMES_OF_FLATS.index(spelling.letter_name.to_s)
  end
end

#double_sharpsObject



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

def double_sharps
  spellings.select(&:double_sharp?).sort_by do |spelling|
    ORDERED_LETTER_NAMES_OF_SHARPS.index(spelling.letter_name.to_s)
  end
end

#enharmonic_equivalent?(other) ⇒ Boolean

Returns:

  • (Boolean)


98
99
100
# File 'lib/head_music/key_signature.rb', line 98

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

#flatsObject



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

def flats
  spellings.select(&:flat?).sort_by do |spelling|
    ORDERED_LETTER_NAMES_OF_FLATS.index(spelling.letter_name.to_s)
  end
end

#nameObject



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

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

#num_alterationsObject



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

def num_alterations
  num_sharps + num_flats
end

#num_flatsObject



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

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

#num_sharpsObject



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

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

#sharpsObject



37
38
39
40
41
# File 'lib/head_music/key_signature.rb', line 37

def sharps
  spellings.select(&:sharp?).sort_by do |spelling|
    ORDERED_LETTER_NAMES_OF_SHARPS.index(spelling.letter_name.to_s)
  end
end

#spellingsObject



33
34
35
# File 'lib/head_music/key_signature.rb', line 33

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

#to_sObject



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

def to_s
  if sharps.any?
    (sharps.length == 1) ? "1 sharp" : "#{sharps.length} sharps"
  elsif flats.any?
    (flats.length == 1) ? "1 flat" : "#{flats.length} flats"
  else
    "no sharps or flats"
  end
end