Class: HeadMusic::Notation::ABC::DurationWriter
- Inherits:
-
Object
- Object
- HeadMusic::Notation::ABC::DurationWriter
- Defined in:
- lib/head_music/notation/abc/duration_writer.rb
Overview
Converts a HeadMusic::Rudiment::RhythmicValue back into the ABC note-length multiplier string relative to the tune’s unit note length — the inverse of DurationResolver.
Instance Attribute Summary collapse
-
#unit_note_length ⇒ Object
readonly
Returns the value of attribute unit_note_length.
Instance Method Summary collapse
-
#format_multiplier(multiplier) ⇒ Object
private
-
#initialize(unit_note_length) ⇒ DurationWriter
constructor
A new instance of DurationWriter.
-
#multiplier_string(rhythmic_value) ⇒ Object
-
#multiplier_string_for_fraction(fraction, rhythmic_value) ⇒ Object
For the part of a value that falls inside one bar; the rhythmic value is only named in the error.
-
#power_of_two?(integer) ⇒ Boolean
private
-
#raise_error(message, rhythmic_value) ⇒ Object
private
-
#total_fraction(rhythmic_value) ⇒ Object
private
RhythmicValue’s own value methods return Floats; rebuild the fraction from integer parts so the multiplier arithmetic stays exact.
-
#validate_fraction!(fraction, rhythmic_value) ⇒ Object
private
Constructor Details
#initialize(unit_note_length) ⇒ DurationWriter
Returns a new instance of DurationWriter.
9 10 11 |
# File 'lib/head_music/notation/abc/duration_writer.rb', line 9 def initialize(unit_note_length) @unit_note_length = Rational(unit_note_length) end |
Instance Attribute Details
#unit_note_length ⇒ Object (readonly)
Returns the value of attribute unit_note_length.
7 8 9 |
# File 'lib/head_music/notation/abc/duration_writer.rb', line 7 def unit_note_length @unit_note_length end |
Instance Method Details
#format_multiplier(multiplier) ⇒ Object (private)
46 47 48 49 50 51 |
# File 'lib/head_music/notation/abc/duration_writer.rb', line 46 def format_multiplier(multiplier) return "" if multiplier == 1 return multiplier.numerator.to_s if multiplier.denominator == 1 "#{multiplier.numerator}/#{multiplier.denominator}" end |
#multiplier_string(rhythmic_value) ⇒ Object
13 14 15 |
# File 'lib/head_music/notation/abc/duration_writer.rb', line 13 def multiplier_string(rhythmic_value) multiplier_string_for_fraction(total_fraction(rhythmic_value), rhythmic_value) end |
#multiplier_string_for_fraction(fraction, rhythmic_value) ⇒ Object
For the part of a value that falls inside one bar; the rhythmic value is only named in the error.
19 20 21 22 |
# File 'lib/head_music/notation/abc/duration_writer.rb', line 19 def multiplier_string_for_fraction(fraction, rhythmic_value) validate_fraction!(fraction, rhythmic_value) format_multiplier(fraction / unit_note_length) end |
#power_of_two?(integer) ⇒ Boolean (private)
53 54 55 |
# File 'lib/head_music/notation/abc/duration_writer.rb', line 53 def power_of_two?(integer) (integer & (integer - 1)).zero? end |
#raise_error(message, rhythmic_value) ⇒ Object (private)
57 58 59 |
# File 'lib/head_music/notation/abc/duration_writer.rb', line 57 def raise_error(, rhythmic_value) raise HeadMusic::Notation::ABC::RenderError, "#{}: #{rhythmic_value}" end |
#total_fraction(rhythmic_value) ⇒ Object (private)
RhythmicValue’s own value methods return Floats; rebuild the fraction from integer parts so the multiplier arithmetic stays exact. A tied chain collapses to one multiplier, round-tripping tokens like “A5”.
29 30 31 32 33 34 |
# File 'lib/head_music/notation/abc/duration_writer.rb', line 29 def total_fraction(rhythmic_value) fraction = HeadMusic::Notation::DottedDuration.dotted_unit_fraction(rhythmic_value) tied_value = rhythmic_value.tied_value fraction += total_fraction(tied_value) if tied_value fraction end |
#validate_fraction!(fraction, rhythmic_value) ⇒ Object (private)
36 37 38 39 40 41 42 43 44 |
# File 'lib/head_music/notation/abc/duration_writer.rb', line 36 def validate_fraction!(fraction, rhythmic_value) max_fraction = DurationResolver::MAX_FRACTION if fraction > max_fraction raise_error("note length exceeds #{max_fraction.to_i} whole notes", rhythmic_value) end return if power_of_two?(fraction.denominator) raise_error("note length #{fraction} is not expressible in binary note values", rhythmic_value) end |