Class: HeadMusic::Notation::ABC::KeyMapper
- Inherits:
-
Object
- Object
- HeadMusic::Notation::ABC::KeyMapper
- 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
- ABC_SUFFIXES_BY_MODE =
MODE_NAMES_BY_PREFIX is many-to-one, so rendering uses this explicit inverse map. Every suffix here parses back to an equal key signature (ionian/aeolian differ from major/minor only in name, not alterations).
{ "major" => "", "ionian" => "", "minor" => "m", "aeolian" => "m", "dorian" => "dor", "phrygian" => "phr", "lydian" => "lyd", "mixolydian" => "mix", "locrian" => "loc" }.freeze
Instance Attribute Summary collapse
-
#line_number ⇒ Object
readonly
Returns the value of attribute line_number.
-
#value ⇒ Object
readonly
Returns the value of attribute value.
Class Method Summary collapse
-
.abc_value(key_signature) ⇒ Object
Returns the ABC K: field value for a key signature.
-
.mode_suffix(key_signature) ⇒ Object
private
-
.raise_render_error(message) ⇒ Object
private
-
.tonic_string(key_signature) ⇒ Object
private
Instance Method Summary collapse
-
#initialize(value, line_number: nil) ⇒ KeyMapper
constructor
A new instance of KeyMapper.
-
#key_signature ⇒ Object
-
#key_signature_name ⇒ Object
-
#match ⇒ Object
private
-
#mode_name ⇒ Object
private
-
#raise_parse_error(message) ⇒ Object
private
-
#tonic ⇒ Object
private
Constructor Details
#initialize(value, line_number: nil) ⇒ KeyMapper
Returns a new instance of KeyMapper.
70 71 72 73 |
# File 'lib/head_music/notation/abc/key_mapper.rb', line 70 def initialize(value, line_number: nil) @value = value.to_s.strip @line_number = line_number end |
Instance Attribute Details
#line_number ⇒ Object (readonly)
Returns the value of attribute line_number.
68 69 70 |
# File 'lib/head_music/notation/abc/key_mapper.rb', line 68 def line_number @line_number end |
#value ⇒ Object (readonly)
Returns the value of attribute value.
68 69 70 |
# File 'lib/head_music/notation/abc/key_mapper.rb', line 68 def value @value end |
Class Method Details
.abc_value(key_signature) ⇒ Object
Returns the ABC K: field value for a key signature.
39 40 41 42 |
# File 'lib/head_music/notation/abc/key_mapper.rb', line 39 def self.abc_value(key_signature) key_signature = HeadMusic::Rudiment::KeySignature.get(key_signature) "#{tonic_string(key_signature)}#{mode_suffix(key_signature)}" end |
.mode_suffix(key_signature) ⇒ Object (private)
57 58 59 60 |
# File 'lib/head_music/notation/abc/key_mapper.rb', line 57 def self.mode_suffix(key_signature) ABC_SUFFIXES_BY_MODE[key_signature.scale_type.name.to_s] || raise_render_error("Cannot render scale type #{key_signature.scale_type} in an ABC K: field") end |
.raise_render_error(message) ⇒ Object (private)
63 64 65 |
# File 'lib/head_music/notation/abc/key_mapper.rb', line 63 def self.raise_render_error() raise HeadMusic::Notation::ABC::RenderError, end |
.tonic_string(key_signature) ⇒ Object (private)
44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/head_music/notation/abc/key_mapper.rb', line 44 def self.tonic_string(key_signature) spelling = key_signature.tonic_spelling alteration = spelling.alteration if alteration && (alteration.double_sharp? || alteration.double_flat?) raise_render_error("Cannot render double-altered tonic #{spelling} in an ABC K: field") end # ABC convention uses ASCII "#"/"b" rather than the unicode signs # that Spelling#to_s produces. "#{spelling.letter_name}#{alteration&.ascii}" end |
Instance Method Details
#key_signature ⇒ Object
79 80 81 |
# File 'lib/head_music/notation/abc/key_mapper.rb', line 79 def key_signature HeadMusic::Rudiment::KeySignature.get(key_signature_name) end |
#key_signature_name ⇒ Object
75 76 77 |
# File 'lib/head_music/notation/abc/key_mapper.rb', line 75 def key_signature_name "#{tonic} #{mode_name}" end |
#match ⇒ Object (private)
85 86 87 88 |
# File 'lib/head_music/notation/abc/key_mapper.rb', line 85 def match @match ||= KEY_PATTERN.match(value) || raise_parse_error("Unrecognized key") end |
#mode_name ⇒ Object (private)
94 95 96 97 98 99 100 101 |
# File 'lib/head_music/notation/abc/key_mapper.rb', line 94 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)
103 104 105 106 107 108 109 |
# File 'lib/head_music/notation/abc/key_mapper.rb', line 103 def raise_parse_error() raise HeadMusic::Notation::ABC::ParseError.new( "#{} in K: field value #{value.inspect}", line_number: line_number, snippet: value ) end |
#tonic ⇒ Object (private)
90 91 92 |
# File 'lib/head_music/notation/abc/key_mapper.rb', line 90 def tonic match[1] + match[2] end |