Class: HeadMusic::Notation::LilyPond::RenderPlan
- Inherits:
-
Object
- Object
- HeadMusic::Notation::LilyPond::RenderPlan
- Defined in:
- lib/head_music/notation/lily_pond/render_plan.rb
Overview
The computed musical facts a Writer needs to serialize a composition: the token for every placement and the key/time signatures in force at each measure. Construction eagerly computes everything that can raise on unmappable keys, durations, or alterations, so a RenderPlan that builds successfully cannot fail assembly on those grounds.
Instance Attribute Summary collapse
-
#composition ⇒ Object
readonly
Returns the value of attribute composition.
Instance Method Summary collapse
-
#bar_numbers ⇒ Object
-
#chord_token(placement) ⇒ Object
private
-
#effective_meter(bar_number) ⇒ Object
-
#first_measure_key ⇒ Object
-
#first_measure_meter ⇒ Object
-
#initialize(composition) ⇒ RenderPlan
constructor
A new instance of RenderPlan.
-
#measure_key_changes ⇒ Object
-
#measure_time_changes ⇒ Object
-
#note_token(placement) ⇒ Object
private
-
#placements_by_bar(voice) ⇒ Object
-
#precompute_eager_data ⇒ Object
private
Everything that can raise on unmappable keys, durations, or alterations is computed here so it raises at construction, before the Writer assembles output.
-
#rest_token(placement) ⇒ Object
private
-
#token(placement) ⇒ Object
private
A tied chain within a placement joins its links with the tie mark; a chain of rests emits consecutive untied rests, and a tied chord repeats the whole chord.
-
#tokens_by_placement ⇒ Object
Constructor Details
#initialize(composition) ⇒ RenderPlan
Returns a new instance of RenderPlan.
11 12 13 14 |
# File 'lib/head_music/notation/lily_pond/render_plan.rb', line 11 def initialize(composition) @composition = composition precompute_eager_data end |
Instance Attribute Details
#composition ⇒ Object (readonly)
Returns the value of attribute composition.
9 10 11 |
# File 'lib/head_music/notation/lily_pond/render_plan.rb', line 9 def composition @composition end |
Instance Method Details
#bar_numbers ⇒ Object
16 17 18 |
# File 'lib/head_music/notation/lily_pond/render_plan.rb', line 16 def composition...composition. end |
#chord_token(placement) ⇒ Object (private)
89 90 91 92 |
# File 'lib/head_music/notation/lily_pond/render_plan.rb', line 89 def chord_token(placement) body = "<#{placement.pitches.sort.map { |pitch| PitchWriter.token(pitch) }.join(" ")}>" placement.rhythmic_value.tied_chain.map { |link| "#{body}#{DurationWriter.token(link)}" }.join("~ ") end |
#effective_meter(bar_number) ⇒ Object
41 42 43 44 |
# File 'lib/head_music/notation/lily_pond/render_plan.rb', line 41 def effective_meter() = measure_time_changes.keys.select { |number| number <= }.max ? measure_time_changes[] : composition.meter end |
#first_measure_key ⇒ Object
32 33 34 35 |
# File 'lib/head_music/notation/lily_pond/render_plan.rb', line 32 def first_measure_key @first_measure_key ||= measure_key_changes[.first] || KeyMapper.token(composition.key_signature) end |
#first_measure_meter ⇒ Object
37 38 39 |
# File 'lib/head_music/notation/lily_pond/render_plan.rb', line 37 def first_measure_meter @first_measure_meter ||= effective_meter(.first) end |
#measure_key_changes ⇒ Object
20 21 22 23 24 |
# File 'lib/head_music/notation/lily_pond/render_plan.rb', line 20 def measure_key_changes @measure_key_changes ||= .zip(composition.).filter_map { |, | [, KeyMapper.token(.key_signature)] if .key_signature }.to_h end |
#measure_time_changes ⇒ Object
26 27 28 29 30 |
# File 'lib/head_music/notation/lily_pond/render_plan.rb', line 26 def measure_time_changes @measure_time_changes ||= .zip(composition.).filter_map { |, | [, .meter] if .meter }.to_h end |
#note_token(placement) ⇒ Object (private)
84 85 86 87 |
# File 'lib/head_music/notation/lily_pond/render_plan.rb', line 84 def note_token(placement) pitch_token = PitchWriter.token(placement.pitch) placement.rhythmic_value.tied_chain.map { |link| "#{pitch_token}#{DurationWriter.token(link)}" }.join("~ ") end |
#placements_by_bar(voice) ⇒ Object
46 47 48 49 |
# File 'lib/head_music/notation/lily_pond/render_plan.rb', line 46 def (voice) @placements_by_bar ||= {} @placements_by_bar[voice] ||= voice.placements.group_by { |placement| placement.position. } end |
#precompute_eager_data ⇒ Object (private)
Everything that can raise on unmappable keys, durations, or alterations is computed here so it raises at construction, before the Writer assembles output.
62 63 64 65 66 67 68 |
# File 'lib/head_music/notation/lily_pond/render_plan.rb', line 62 def precompute_eager_data first_measure_key first_measure_meter measure_key_changes measure_time_changes tokens_by_placement end |
#rest_token(placement) ⇒ Object (private)
80 81 82 |
# File 'lib/head_music/notation/lily_pond/render_plan.rb', line 80 def rest_token(placement) placement.rhythmic_value.tied_chain.map { |link| "r#{DurationWriter.token(link)}" }.join(" ") end |
#token(placement) ⇒ Object (private)
A tied chain within a placement joins its links with the tie mark; a chain of rests emits consecutive untied rests, and a tied chord repeats the whole chord.
73 74 75 76 77 78 |
# File 'lib/head_music/notation/lily_pond/render_plan.rb', line 73 def token(placement) return rest_token(placement) if placement.rest? return chord_token(placement) if placement.chord? note_token(placement) end |
#tokens_by_placement ⇒ Object
51 52 53 54 55 |
# File 'lib/head_music/notation/lily_pond/render_plan.rb', line 51 def tokens_by_placement @tokens_by_placement ||= composition.voices.flat_map(&:placements).to_h do |placement| [placement, token(placement)] end end |