Class: HeadMusic::Time::Conductor
- Inherits:
-
Object
- Object
- HeadMusic::Time::Conductor
- Defined in:
- lib/head_music/time/conductor.rb
Overview
Representation of a conductor track for musical material
The Conductor class synchronizes three different time representations:
- Clock time: elapsed nanoseconds (source of truth)
- Musical position: bars:beats:ticks:subticks notation
- SMPTE timecode: hours:minutes:seconds:frames
Each moment in a track corresponds to all three positions simultaneously. The conductor handles conversions between these representations based on the current tempo, meter, and framerate.
Instance Attribute Summary collapse
-
#framerate ⇒ Integer
Frames per second for SMPTE conversions.
-
#meter_map ⇒ MeterMap
readonly
The meter map for this conductor.
-
#starting_musical_position ⇒ MusicalPosition
The musical position at clock time 0.
-
#starting_smpte_timecode ⇒ SmpteTimecode
The SMPTE timecode at clock time 0.
-
#tempo_map ⇒ TempoMap
readonly
The tempo map for this conductor.
Instance Method Summary collapse
-
#clock_to_musical(clock_position) ⇒ MusicalPosition
Convert clock position to musical position.
-
#clock_to_smpte(clock_position) ⇒ SmpteTimecode
Convert clock position to SMPTE timecode.
-
#initialize(starting_musical_position: nil, starting_smpte_timecode: nil, framerate: SmpteTimecode::DEFAULT_FRAMERATE, starting_tempo: nil, starting_meter: nil, tempo_map: nil, meter_map: nil) ⇒ Conductor
constructor
Create a new conductor.
-
#musical_time_converter ⇒ Object
private
A fresh musical-time converter over the current maps and starting position (starting_musical_position is a mutable accessor), rebuilt per call rather than memoized so reassignment takes effect.
-
#musical_to_clock(musical_position) ⇒ ClockPosition
Convert musical position to clock position.
-
#smpte_converter ⇒ Object
private
A fresh SMPTE converter reflecting the current framerate and starting timecode.
-
#smpte_to_clock(smpte_timecode) ⇒ ClockPosition
Convert SMPTE timecode to clock position.
-
#starting_meter ⇒ HeadMusic::Rudiment::Meter
The initial meter (delegates to meter_map).
-
#starting_tempo ⇒ HeadMusic::Rudiment::Tempo
The initial tempo (delegates to tempo_map).
Constructor Details
#initialize(starting_musical_position: nil, starting_smpte_timecode: nil, framerate: SmpteTimecode::DEFAULT_FRAMERATE, starting_tempo: nil, starting_meter: nil, tempo_map: nil, meter_map: nil) ⇒ Conductor
Create a new conductor
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/head_music/time/conductor.rb', line 68 def initialize( starting_musical_position: nil, starting_smpte_timecode: nil, framerate: SmpteTimecode::DEFAULT_FRAMERATE, starting_tempo: nil, starting_meter: nil, tempo_map: nil, meter_map: nil ) @starting_musical_position = starting_musical_position || MusicalPosition.new @starting_smpte_timecode = starting_smpte_timecode || SmpteTimecode.new(0, 0, 0, 0, framerate: framerate) @framerate = framerate # Create or use provided maps @tempo_map = tempo_map || TempoMap.new( starting_tempo: starting_tempo || HeadMusic::Rudiment::Tempo.new("quarter", 120), starting_position: @starting_musical_position ) @meter_map = meter_map || MeterMap.new( starting_meter: starting_meter || "4/4", starting_position: @starting_musical_position ) end |
Instance Attribute Details
#framerate ⇒ Integer
Returns frames per second for SMPTE conversions.
41 42 43 |
# File 'lib/head_music/time/conductor.rb', line 41 def framerate @framerate end |
#meter_map ⇒ MeterMap (readonly)
Returns the meter map for this conductor.
47 48 49 |
# File 'lib/head_music/time/conductor.rb', line 47 def meter_map @meter_map end |
#starting_musical_position ⇒ MusicalPosition
Returns the musical position at clock time 0.
35 36 37 |
# File 'lib/head_music/time/conductor.rb', line 35 def starting_musical_position @starting_musical_position end |
#starting_smpte_timecode ⇒ SmpteTimecode
Returns the SMPTE timecode at clock time 0.
38 39 40 |
# File 'lib/head_music/time/conductor.rb', line 38 def starting_smpte_timecode @starting_smpte_timecode end |
#tempo_map ⇒ TempoMap (readonly)
Returns the tempo map for this conductor.
44 45 46 |
# File 'lib/head_music/time/conductor.rb', line 44 def tempo_map @tempo_map end |
Instance Method Details
#clock_to_musical(clock_position) ⇒ MusicalPosition
Convert clock position to musical position
Uses the tempo map to determine how many beats have elapsed, accounting for tempo changes along the timeline.
99 100 101 |
# File 'lib/head_music/time/conductor.rb', line 99 def clock_to_musical(clock_position) musical_time_converter.clock_to_musical(clock_position) end |
#clock_to_smpte(clock_position) ⇒ SmpteTimecode
Convert clock position to SMPTE timecode
Uses the framerate to determine the timecode.
120 121 122 |
# File 'lib/head_music/time/conductor.rb', line 120 def clock_to_smpte(clock_position) smpte_converter.clock_to_smpte(clock_position) end |
#musical_time_converter ⇒ Object (private)
A fresh musical-time converter over the current maps and starting position (starting_musical_position is a mutable accessor), rebuilt per call rather than memoized so reassignment takes effect.
139 140 141 142 143 144 145 |
# File 'lib/head_music/time/conductor.rb', line 139 def musical_time_converter MusicalTimeConverter.new( tempo_map: tempo_map, meter_map: meter_map, starting_musical_position: starting_musical_position ) end |
#musical_to_clock(musical_position) ⇒ ClockPosition
Convert musical position to clock position
Uses the tempo map to determine how much clock time has elapsed based on the musical position, accounting for tempo changes.
110 111 112 |
# File 'lib/head_music/time/conductor.rb', line 110 def musical_to_clock(musical_position) musical_time_converter.musical_to_clock(musical_position) end |
#smpte_converter ⇒ Object (private)
A fresh SMPTE converter reflecting the current framerate and starting timecode. Both are mutable accessors, so it is rebuilt per call rather than memoized, ensuring a reassigned framerate takes effect.
150 151 152 |
# File 'lib/head_music/time/conductor.rb', line 150 def smpte_converter SmpteConverter.new(framerate: framerate, starting_smpte_timecode: starting_smpte_timecode) end |
#smpte_to_clock(smpte_timecode) ⇒ ClockPosition
Convert SMPTE timecode to clock position
Uses the framerate to determine the clock time.
130 131 132 |
# File 'lib/head_music/time/conductor.rb', line 130 def smpte_to_clock(smpte_timecode) smpte_converter.smpte_to_clock(smpte_timecode) end |
#starting_meter ⇒ HeadMusic::Rudiment::Meter
Returns the initial meter (delegates to meter_map).
55 56 57 |
# File 'lib/head_music/time/conductor.rb', line 55 def starting_meter meter_map.events.first.meter end |
#starting_tempo ⇒ HeadMusic::Rudiment::Tempo
Returns the initial tempo (delegates to tempo_map).
50 51 52 |
# File 'lib/head_music/time/conductor.rb', line 50 def starting_tempo tempo_map.events.first.tempo end |