Class: HeadMusic::Notation::MusicXML::BeamGrouper
- Inherits:
-
Object
- Object
- HeadMusic::Notation::MusicXML::BeamGrouper
- Defined in:
- lib/head_music/notation/music_xml/beam_grouper.rb
Overview
Computes MusicXML
Defined Under Namespace
Instance Attribute Summary collapse
-
#events ⇒ Object
readonly
private
Returns the value of attribute events.
-
#group_unit_divisions ⇒ Object
readonly
private
Returns the value of attribute group_unit_divisions.
Class Method Summary collapse
Instance Method Summary collapse
-
#add_level_beams(group, level, member_beams) ⇒ Object
private
-
#annotate ⇒ Object
-
#beams_for_group(group) ⇒ Object
private
Phase B: emit one Array
per member, parallel to the group's events. -
#break_before?(index) ⇒ Boolean
private
-
#emit_run(run, level, member_beams) ⇒ Object
private
-
#groups ⇒ Object
private
Phase A: segment event indices into groups of consecutive indices.
-
#initialize(events, group_unit_divisions) ⇒ BeamGrouper
constructor
A new instance of BeamGrouper.
-
#participating(group, level) ⇒ Object
private
Maximal runs of consecutive-within-the-group positions whose event has levels >= level.
-
#run_type(offset, run_size) ⇒ Object
private
Constructor Details
#initialize(events, group_unit_divisions) ⇒ BeamGrouper
Returns a new instance of BeamGrouper.
22 23 24 25 |
# File 'lib/head_music/notation/music_xml/beam_grouper.rb', line 22 def initialize(events, group_unit_divisions) @events = events @group_unit_divisions = group_unit_divisions end |
Instance Attribute Details
#events ⇒ Object (readonly, private)
Returns the value of attribute events.
33 34 35 |
# File 'lib/head_music/notation/music_xml/beam_grouper.rb', line 33 def events @events end |
#group_unit_divisions ⇒ Object (readonly, private)
Returns the value of attribute group_unit_divisions.
33 34 35 |
# File 'lib/head_music/notation/music_xml/beam_grouper.rb', line 33 def group_unit_divisions @group_unit_divisions end |
Class Method Details
.annotate(events, group_unit_divisions) ⇒ Object
18 19 20 |
# File 'lib/head_music/notation/music_xml/beam_grouper.rb', line 18 def self.annotate(events, group_unit_divisions) new(events, group_unit_divisions).annotate end |
Instance Method Details
#add_level_beams(group, level, member_beams) ⇒ Object (private)
68 69 70 71 72 |
# File 'lib/head_music/notation/music_xml/beam_grouper.rb', line 68 def add_level_beams(group, level, member_beams) participating(group, level).each do |run| emit_run(run, level, member_beams) end end |
#annotate ⇒ Object
27 28 29 |
# File 'lib/head_music/notation/music_xml/beam_grouper.rb', line 27 def annotate groups.flat_map { |group| beams_for_group(group) } end |
#beams_for_group(group) ⇒ Object (private)
Phase B: emit one Array
59 60 61 62 63 64 65 66 |
# File 'lib/head_music/notation/music_xml/beam_grouper.rb', line 59 def beams_for_group(group) return [[]] if group.size == 1 member_beams = Array.new(group.size) { [] } max_level = group.map { |i| events[i].levels }.max (1..max_level).each { |level| add_level_beams(group, level, member_beams) } member_beams end |
#break_before?(index) ⇒ Boolean (private)
48 49 50 51 52 53 54 55 56 |
# File 'lib/head_music/notation/music_xml/beam_grouper.rb', line 48 def break_before?(index) event = events[index] return true if event.levels.zero? return true if events[index - 1].levels.zero? return true if event.beam_break_before == true return false if event.beam_break_before == false (event.onset % group_unit_divisions).zero? end |
#emit_run(run, level, member_beams) ⇒ Object (private)
86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/head_music/notation/music_xml/beam_grouper.rb', line 86 def emit_run(run, level, member_beams) if run.size == 1 position = run.first # A lone member at this level gets a partial beam (hook). It points # backward unless it is the group's first member, which has nothing # to hook back to. member_beams[position] << Beam.new(number: level, type: position.zero? ? "forward hook" : "backward hook") return end run.each_with_index do |position, offset| member_beams[position] << Beam.new(number: level, type: run_type(offset, run.size)) end end |
#groups ⇒ Object (private)
Phase A: segment event indices into groups of consecutive indices.
36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/head_music/notation/music_xml/beam_grouper.rb', line 36 def groups result = [] events.each_index do |i| if i.zero? || break_before?(i) result << [i] else result.last << i end end result end |
#participating(group, level) ⇒ Object (private)
Maximal runs of consecutive-within-the-group positions whose event has
levels >= level. Positions are indices into group (and member_beams).
76 77 78 79 80 81 82 83 84 |
# File 'lib/head_music/notation/music_xml/beam_grouper.rb', line 76 def participating(group, level) runs = [] group.each_with_index do |event_index, position| if events[event_index].levels >= level (runs.last && runs.last.last == position - 1) ? runs.last << position : runs << [position] end end runs end |
#run_type(offset, run_size) ⇒ Object (private)
101 102 103 104 105 106 |
# File 'lib/head_music/notation/music_xml/beam_grouper.rb', line 101 def run_type(offset, run_size) return "begin" if offset.zero? return "end" if offset == run_size - 1 "continue" end |