Class: HeadMusic::Time::MeterMap
- Inherits:
-
Object
- Object
- HeadMusic::Time::MeterMap
- Includes:
- EventMapSupport
- Defined in:
- lib/head_music/time/meter_map.rb
Overview
Manages meter (time signature) changes along a musical timeline
A MeterMap maintains a sorted list of meter changes at specific musical positions, allowing you to determine which meter is active at any point and iterate through meter segments for musical position calculations.
Instance Attribute Summary collapse
-
#events ⇒ Array<MeterEvent>
readonly
All meter events in chronological order.
Instance Method Summary collapse
- #add_change(position, meter_or_identifier) ⇒ Object
- #clear_changes ⇒ Object
- #compare_positions(first_position, second_position) ⇒ Object included from EventMapSupport private
- #each_segment(from_position, to_position) {|current_pos, to_position, current_meter| ... } ⇒ Object
-
#initialize(starting_meter: nil, starting_position: nil) ⇒ MeterMap
constructor
A new instance of MeterMap.
- #meter_at(position) ⇒ Object
- #position_tuple(position) ⇒ Object included from EventMapSupport private
- #positions_equal?(first_position, second_position) ⇒ Boolean included from EventMapSupport private
- #remove_change(position) ⇒ Object
- #sort_events! ⇒ Object included from EventMapSupport private
Constructor Details
#initialize(starting_meter: nil, starting_position: nil) ⇒ MeterMap
Returns a new instance of MeterMap.
31 32 33 34 35 |
# File 'lib/head_music/time/meter_map.rb', line 31 def initialize(starting_meter: nil, starting_position: nil) starting_meter = HeadMusic::Rudiment::Meter.get(starting_meter || "4/4") starting_position ||= MusicalPosition.new @events = [MeterEvent.new(starting_position, starting_meter)] end |
Instance Attribute Details
#events ⇒ Array<MeterEvent> (readonly)
Returns all meter events in chronological order.
29 30 31 |
# File 'lib/head_music/time/meter_map.rb', line 29 def events @events end |
Instance Method Details
#add_change(position, meter_or_identifier) ⇒ Object
37 38 39 40 41 42 43 44 |
# File 'lib/head_music/time/meter_map.rb', line 37 def add_change(position, meter_or_identifier) remove_change(position) meter = meter_or_identifier.is_a?(HeadMusic::Rudiment::Meter) ? meter_or_identifier : HeadMusic::Rudiment::Meter.get(meter_or_identifier) event = MeterEvent.new(position, meter) @events << event sort_events! event end |
#clear_changes ⇒ Object
52 53 54 |
# File 'lib/head_music/time/meter_map.rb', line 52 def clear_changes @events = [@events.first] end |
#compare_positions(first_position, second_position) ⇒ Object (private) Originally defined in module EventMapSupport
#each_segment(from_position, to_position) {|current_pos, to_position, current_meter| ... } ⇒ Object
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/head_music/time/meter_map.rb', line 63 def each_segment(from_position, to_position) relevant_events = @events.select do |event| compare_positions(event.position, to_position) < 0 end current_pos = from_position current_meter = meter_at(from_position) relevant_events.each do |event| next if compare_positions(event.position, from_position) <= 0 yield current_pos, event.position, current_meter current_pos = event.position current_meter = event.meter end yield current_pos, to_position, current_meter end |
#meter_at(position) ⇒ Object
56 57 58 59 60 61 |
# File 'lib/head_music/time/meter_map.rb', line 56 def meter_at(position) active_event = @events.reverse.find do |event| compare_positions(event.position, position) <= 0 end active_event&.meter || @events.first.meter end |
#position_tuple(position) ⇒ Object (private) Originally defined in module EventMapSupport
#positions_equal?(first_position, second_position) ⇒ Boolean (private) Originally defined in module EventMapSupport
#remove_change(position) ⇒ Object
46 47 48 49 50 |
# File 'lib/head_music/time/meter_map.rb', line 46 def remove_change(position) @events.reject! do |event| event != @events.first && positions_equal?(event.position, position) end end |