Class: HeadMusic::Notation::ABC::ChordReader
- Inherits:
-
Object
- Object
- HeadMusic::Notation::ABC::ChordReader
- Defined in:
- lib/head_music/notation/abc/chord_reader.rb
Overview
Resolves a bracket-chord token into the pitches it sounds and the one length its notes share.
Instance Attribute Summary collapse
-
#duration_resolver ⇒ Object
readonly
private
Returns the value of attribute duration_resolver.
Instance Method Summary collapse
-
#ensure_unique_pitches(pitches, token) ⇒ Object
private
-
#initialize(duration_resolver) ⇒ ChordReader
constructor
A new instance of ChordReader.
-
#read(token, pitch_builder) ⇒ Object
Returns the chord’s pitches and its shared inner length.
-
#snippet(token) ⇒ Object
private
-
#uniform_length(token) ⇒ Object
private
ABC 2.1 sec.
Constructor Details
#initialize(duration_resolver) ⇒ ChordReader
Returns a new instance of ChordReader.
6 7 8 |
# File 'lib/head_music/notation/abc/chord_reader.rb', line 6 def initialize(duration_resolver) @duration_resolver = duration_resolver end |
Instance Attribute Details
#duration_resolver ⇒ Object (readonly, private)
Returns the value of attribute duration_resolver.
23 24 25 |
# File 'lib/head_music/notation/abc/chord_reader.rb', line 23 def duration_resolver @duration_resolver end |
Instance Method Details
#ensure_unique_pitches(pitches, token) ⇒ Object (private)
25 26 27 28 29 30 31 32 |
# File 'lib/head_music/notation/abc/chord_reader.rb', line 25 def ensure_unique_pitches(pitches, token) return if pitches.uniq.length == pitches.length raise ParseError.new( "Chord pitches must be unique", line_number: token.line, snippet: snippet(token) ) end |
#read(token, pitch_builder) ⇒ Object
Returns the chord’s pitches and its shared inner length. Chord pitches resolve in bracket order, so an explicit accidental inside a chord persists for the rest of the bar like any other.
13 14 15 16 17 18 19 |
# File 'lib/head_music/notation/abc/chord_reader.rb', line 13 def read(token, pitch_builder) pitches = token.notes.map do |note| pitch_builder.pitch(note.letter, note.octave_marks, note.accidental) end ensure_unique_pitches(pitches, token) [pitches, uniform_length(token)] end |
#snippet(token) ⇒ Object (private)
49 50 51 52 53 54 |
# File 'lib/head_music/notation/abc/chord_reader.rb', line 49 def snippet(token) inner = token.notes.map do |note| "#{note.accidental}#{note.letter}#{note.octave_marks}#{note.length}" end.join "[#{inner}]" end |
#uniform_length(token) ⇒ Object (private)
ABC 2.1 sec. 4.17 allows per-note lengths only when they agree; the shared inner length then multiplies with any outer length. Unequal lengths (whose ABC meaning is “the duration of the first note”) would need silent reinterpretation to fit one rhythmic value, so we reject.
38 39 40 41 42 43 44 45 46 47 |
# File 'lib/head_music/notation/abc/chord_reader.rb', line 38 def uniform_length(token) fractions = token.notes.map { |note| duration_resolver.length_fraction(note.length) } return fractions.first if fractions.uniq.length == 1 raise ParseError.new( 'Chord notes must share one length; write it after the bracket ("[CEG]2") ' \ 'or repeat it on every note ("[C2E2G2]")', line_number: token.line, snippet: snippet(token) ) end |