Class: HeadMusic::Time::TempoMap
- Inherits:
-
Object
- Object
- HeadMusic::Time::TempoMap
- Defined in:
- lib/head_music/time/tempo_map.rb
Overview
Manages tempo changes along a musical timeline
A TempoMap maintains a sorted list of tempo changes at specific musical positions, allowing you to determine which tempo is active at any point and iterate through tempo segments for time calculations.
Instance Method Summary collapse
- #add_change(position, beat_value_or_tempo, beats_per_minute = nil) ⇒ Object
-
#change_at(position) ⇒ TempoEvent?
The tempo change starting exactly here.
- #clear_changes ⇒ Object
- #each_segment(from_position, to_position, &block) ⇒ Object
-
#events ⇒ Array<TempoEvent>
All tempo events in chronological order.
-
#initialize(starting_tempo: nil, starting_position: nil) ⇒ TempoMap
constructor
A new instance of TempoMap.
- #remove_change(position) ⇒ Object
- #tempo_at(position) ⇒ Object
Constructor Details
#initialize(starting_tempo: nil, starting_position: nil) ⇒ TempoMap
Returns a new instance of TempoMap.
26 27 28 29 30 31 32 33 |
# File 'lib/head_music/time/tempo_map.rb', line 26 def initialize(starting_tempo: nil, starting_position: nil) starting_tempo ||= HeadMusic::Rudiment::Tempo.new("quarter", 120) starting_position ||= MusicalPosition.new # The opening tempo is not removable: converting a position to clock # time needs a tempo in force from the beginning. @map = EventMap.new(removable_first_event: false) @map.add(starting_position, TempoEvent.new(starting_position, starting_tempo.beat_value.to_s, starting_tempo.beats_per_minute)) end |
Instance Method Details
#add_change(position, beat_value_or_tempo, beats_per_minute = nil) ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/head_music/time/tempo_map.rb', line 40 def add_change(position, beat_value_or_tempo, beats_per_minute = nil) event = if beat_value_or_tempo.is_a?(HeadMusic::Rudiment::Tempo) TempoEvent.new(position, beat_value_or_tempo.beat_value.to_s, beat_value_or_tempo.beats_per_minute).tap do |tempo_event| tempo_event.tempo = beat_value_or_tempo end else TempoEvent.new(position, beat_value_or_tempo, beats_per_minute) end @map.add(position, event) event end |
#change_at(position) ⇒ TempoEvent?
Returns the tempo change starting exactly here.
65 66 67 |
# File 'lib/head_music/time/tempo_map.rb', line 65 def change_at(position) @map.change_at(position)&.value end |
#clear_changes ⇒ Object
56 57 58 |
# File 'lib/head_music/time/tempo_map.rb', line 56 def clear_changes @map.clear end |
#each_segment(from_position, to_position, &block) ⇒ Object
69 70 71 72 73 |
# File 'lib/head_music/time/tempo_map.rb', line 69 def each_segment(from_position, to_position, &block) @map.each_segment(from_position, to_position) do |start_position, end_position, event| block.call(start_position, end_position, event&.tempo || events.first.tempo) end end |
#events ⇒ Array<TempoEvent>
Returns all tempo events in chronological order.
36 37 38 |
# File 'lib/head_music/time/tempo_map.rb', line 36 def events @map.values end |
#remove_change(position) ⇒ Object
52 53 54 |
# File 'lib/head_music/time/tempo_map.rb', line 52 def remove_change(position) @map.remove(position) end |
#tempo_at(position) ⇒ Object
60 61 62 |
# File 'lib/head_music/time/tempo_map.rb', line 60 def tempo_at(position) @map.at(position)&.tempo || events.first.tempo end |