Class: MIDI::Track
Overview
A Track is a list of events.
When you modify the events
array, make sure to call recalc_times so each Event gets its time_from_start
recalculated.
A Track also holds a bitmask that specifies the channels used by the track. This bitmask is set when the track is read from the MIDI file by an IO::SeqReader but is not kept up to date by any other methods.
Constant Summary collapse
- UNNAMED =
'Unnamed'
Instance Attribute Summary collapse
-
#channels_used ⇒ Object
Returns the value of attribute channels_used.
-
#events ⇒ Object
Returns the value of attribute events.
-
#sequence ⇒ Object
readonly
Returns the value of attribute sequence.
Instance Method Summary collapse
-
#each ⇒ Object
Iterate over events.
-
#initialize(sequence) ⇒ Track
constructor
A new instance of Track.
- #instrument ⇒ Object
- #instrument=(str_or_bytes) ⇒ Object
-
#merge(event_list) ⇒ Object
Merges an array of events into our event list.
-
#merge_event_lists(list1, list2) ⇒ Object
Merges two event arrays together.
-
#name ⇒ Object
Return track name.
-
#name=(name) ⇒ Object
Set track name.
-
#quantize(length_or_note) ⇒ Object
Quantize every event.
-
#recalc_delta_from_times(starting_at = 0, list = @events) ⇒ Object
(also: #sort)
The opposite of recalc_times: recalculates delta_time for each event from each event’s time_from_start.
-
#recalc_times(starting_at = 0, list = @events) ⇒ Object
Recalculate start times for all events in
list
from starting_at to end.
Constructor Details
Instance Attribute Details
#channels_used ⇒ Object
Returns the value of attribute channels_used.
62 63 64 |
# File 'lib/midilib/track.rb', line 62 def channels_used @channels_used end |
#events ⇒ Object
Returns the value of attribute events.
62 63 64 |
# File 'lib/midilib/track.rb', line 62 def events @events end |
#sequence ⇒ Object (readonly)
Returns the value of attribute sequence.
63 64 65 |
# File 'lib/midilib/track.rb', line 63 def sequence @sequence end |
Instance Method Details
#each ⇒ Object
Iterate over events.
171 172 173 |
# File 'lib/midilib/track.rb', line 171 def each # :yields: event @events.each { | event | yield event } end |
#instrument ⇒ Object
95 96 97 |
# File 'lib/midilib/track.rb', line 95 def instrument MetaEvent.bytes_as_str(@instrument) end |
#instrument=(str_or_bytes) ⇒ Object
99 100 101 102 103 104 105 106 |
# File 'lib/midilib/track.rb', line 99 def instrument=(str_or_bytes) @instrument = case str_or_bytes when String MetaEvent.str_as_bytes(str_or_bytes) else str_or_bytes end end |
#merge(event_list) ⇒ Object
Merges an array of events into our event list. After merging, the events’ time_from_start values are correct so you don’t need to worry about calling recalc_times.
111 112 113 |
# File 'lib/midilib/track.rb', line 111 def merge(event_list) @events = merge_event_lists(@events, event_list) end |
#merge_event_lists(list1, list2) ⇒ Object
Merges two event arrays together. Does not modify this track.
116 117 118 119 120 121 122 |
# File 'lib/midilib/track.rb', line 116 def merge_event_lists(list1, list2) recalc_times(0, list1) recalc_times(0, list2) list = list1 + list2 recalc_delta_from_times(0, list) return list end |
#name ⇒ Object
Return track name. If there is no name, return UNNAMED.
75 76 77 78 79 80 |
# File 'lib/midilib/track.rb', line 75 def name event = @events.detect { | e | e.kind_of?(MetaEvent) && e. == META_SEQ_NAME } return event ? event.data_as_str : UNNAMED end |
#name=(name) ⇒ Object
Set track name. Replaces or creates a name meta-event.
83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/midilib/track.rb', line 83 def name=(name) event = @events.detect { | e | e.kind_of?(MetaEvent) && e. == META_SEQ_NAME } if event event.data = name else event = MetaEvent.new(META_SEQ_NAME, name, 0) @events[0, 0] = event end end |
#quantize(length_or_note) ⇒ Object
Quantize every event. length_or_note is either a length (1 = quarter, 0.25 = sixteenth, 4 = whole note) or a note name (“sixteenth”, “32nd”, “8th triplet”, “dotted quarter”).
Since each event’s time_from_start is modified, we call recalc_delta_from_times after each event quantizes itself.
130 131 132 133 134 135 136 137 138 139 |
# File 'lib/midilib/track.rb', line 130 def quantize(length_or_note) delta = case length_or_note when String @sequence.note_to_delta(length_or_note) else @sequence.length_to_delta(length_or_note.to_i) end @events.each { | event | event.quantize_to(delta) } recalc_delta_from_times end |
#recalc_delta_from_times(starting_at = 0, list = @events) ⇒ Object Also known as: sort
The opposite of recalc_times: recalculates delta_time for each event from each event’s time_from_start. This is useful, for example, when merging two event lists. As a side-effect, elements from starting_at are sorted by time_from_start.
155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/midilib/track.rb', line 155 def recalc_delta_from_times(starting_at=0, list=@events) prev_time_from_start = 0 # We need to sort the sublist. sublist.sort! does not do what we want. # We call mergesort instead of Array.sort because sort is not stable # (it can mix up the order of events that have the same start time). # See http://wiki.github.com/adamjmurray/cosy/midilib-notes for details. list[starting_at .. -1] = list[starting_at .. -1].mergesort { | e1, e2 | e1.time_from_start <=> e2.time_from_start } list[starting_at .. -1].each { | e | e.delta_time = e.time_from_start - prev_time_from_start prev_time_from_start = e.time_from_start } end |
#recalc_times(starting_at = 0, list = @events) ⇒ Object
Recalculate start times for all events in list
from starting_at to end.
143 144 145 146 147 148 149 |
# File 'lib/midilib/track.rb', line 143 def recalc_times(starting_at=0, list=@events) t = (starting_at == 0) ? 0 : list[starting_at - 1].time_from_start list[starting_at .. -1].each { | e | t += e.delta_time e.time_from_start = t } end |