Class: HeadMusic::Notation::ABC::KeyMapper

Inherits:
Object
  • Object
show all
Defined in:
lib/head_music/notation/abc/key_mapper.rb

Overview

Converts an ABC K: field value into a key signature.

ABC key values like “Ador” or “F#m” cannot be passed directly to KeySignature.get, which splits tonic and scale type on whitespace, so the mode word is normalized into a “tonic mode” string first.

Constant Summary collapse

KEY_PATTERN =
/\A([A-G])([#♯b♭]?)\s*([A-Za-z]*)/
MODE_NAMES_BY_PREFIX =

Mode words are matched case-insensitively on their first three letters, so abbreviations (“dor”) and full names (“Dorian”) both resolve.

{
  "maj" => "major",
  "ion" => "major",
  "min" => "minor",
  "aeo" => "minor",
  "dor" => "dorian",
  "phr" => "phrygian",
  "lyd" => "lydian",
  "mix" => "mixolydian",
  "loc" => "locrian"
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(value, line_number: nil) ⇒ KeyMapper

Returns a new instance of KeyMapper.



25
26
27
28
# File 'lib/head_music/notation/abc/key_mapper.rb', line 25

def initialize(value, line_number: nil)
  @value = value.to_s.strip
  @line_number = line_number
end

Instance Attribute Details

#line_numberObject (readonly)

Returns the value of attribute line_number.



23
24
25
# File 'lib/head_music/notation/abc/key_mapper.rb', line 23

def line_number
  @line_number
end

#valueObject (readonly)

Returns the value of attribute value.



23
24
25
# File 'lib/head_music/notation/abc/key_mapper.rb', line 23

def value
  @value
end

Instance Method Details

#key_signatureObject



34
35
36
# File 'lib/head_music/notation/abc/key_mapper.rb', line 34

def key_signature
  HeadMusic::Rudiment::KeySignature.get(key_signature_name)
end

#key_signature_nameObject



30
31
32
# File 'lib/head_music/notation/abc/key_mapper.rb', line 30

def key_signature_name
  "#{tonic} #{mode_name}"
end

#matchObject (private)



40
41
42
43
# File 'lib/head_music/notation/abc/key_mapper.rb', line 40

def match
  @match ||= KEY_PATTERN.match(value) ||
    raise_parse_error("Unrecognized key")
end

#mode_nameObject (private)



49
50
51
52
53
54
55
56
# File 'lib/head_music/notation/abc/key_mapper.rb', line 49

def mode_name
  word = match[3].downcase
  return "major" if word.empty?
  return "minor" if word == "m"

  MODE_NAMES_BY_PREFIX[word[0, 3]] ||
    raise_parse_error("Unrecognized mode")
end

#raise_parse_error(message) ⇒ Object (private)



58
59
60
61
62
63
64
# File 'lib/head_music/notation/abc/key_mapper.rb', line 58

def raise_parse_error(message)
  raise HeadMusic::Notation::ABC::ParseError.new(
    "#{message} in K: field value #{value.inspect}",
    line_number: line_number,
    snippet: value
  )
end

#tonicObject (private)



45
46
47
# File 'lib/head_music/notation/abc/key_mapper.rb', line 45

def tonic
  match[1] + match[2]
end