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
-
#power_of_two?(integer) ⇒ Boolean
private
-
#raise_error(message, rhythmic_value) ⇒ Object
private
-
#single_fraction(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)
48 49 50 51 52 53 |
# File 'lib/head_music/notation/abc/duration_writer.rb', line 48 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 16 17 |
# File 'lib/head_music/notation/abc/duration_writer.rb', line 13 def multiplier_string(rhythmic_value) fraction = total_fraction(rhythmic_value) validate_fraction!(fraction, rhythmic_value) format_multiplier(fraction / unit_note_length) end |
#power_of_two?(integer) ⇒ Boolean (private)
55 56 57 |
# File 'lib/head_music/notation/abc/duration_writer.rb', line 55 def power_of_two?(integer) (integer & (integer - 1)).zero? end |
#raise_error(message, rhythmic_value) ⇒ Object (private)
59 60 61 |
# File 'lib/head_music/notation/abc/duration_writer.rb', line 59 def raise_error(, rhythmic_value) raise HeadMusic::Notation::ABC::RenderError, "#{}: #{rhythmic_value}" end |
#single_fraction(rhythmic_value) ⇒ Object (private)
31 32 33 34 35 36 |
# File 'lib/head_music/notation/abc/duration_writer.rb', line 31 def single_fraction(rhythmic_value) unit = rhythmic_value.unit dots = rhythmic_value.dots # A value with d dots spans (2^(d+1) - 1) / 2^d of its unit. Rational(unit.numerator, unit.denominator) * Rational((2**(dots + 1)) - 1, 2**dots) 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”.
24 25 26 27 28 29 |
# File 'lib/head_music/notation/abc/duration_writer.rb', line 24 def total_fraction(rhythmic_value) fraction = single_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)
38 39 40 41 42 43 44 45 46 |
# File 'lib/head_music/notation/abc/duration_writer.rb', line 38 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 |