Class: MIDI::Sequence
- Inherits:
-
Object
- Object
- MIDI::Sequence
- Includes:
- Enumerable
- Defined in:
- lib/midilib/sequence.rb
Overview
A MIDI::Sequence contains MIDI::Track objects.
Constant Summary collapse
- UNNAMED =
'Unnamed Sequence'
- DEFAULT_TEMPO =
120
- NOTE_TO_LENGTH =
{ 'whole' => 4.0, 'half' => 2.0, 'quarter' => 1.0, 'eighth' => 0.5, '8th' => 0.5, 'sixteenth' => 0.25, '16th' => 0.25, 'thirty second' => 0.125, 'thirtysecond' => 0.125, '32nd' => 0.125, 'sixty fourth' => 0.0625, 'sixtyfourth' => 0.0625, '64th' => 0.0625 }
Instance Attribute Summary collapse
-
#clocks ⇒ Object
Returns the value of attribute clocks.
-
#denom ⇒ Object
Returns the value of attribute denom.
-
#format ⇒ Object
The MIDI file format (0, 1, or 2).
-
#numer ⇒ Object
Returns the value of attribute numer.
-
#ppqn ⇒ Object
Pulses (i.e. clocks) Per Quarter Note resolution for the sequence.
-
#qnotes ⇒ Object
Returns the value of attribute qnotes.
-
#reader_class ⇒ Object
The class to use for reading MIDI from a stream.
-
#tracks ⇒ Object
Array with all tracks for the sequence.
-
#writer_class ⇒ Object
The class to use for writeing MIDI from a stream.
Instance Method Summary collapse
-
#beats_per_minute ⇒ Object
(also: #bpm, #tempo)
Returns the song tempo in beats per minute.
-
#each(&block) ⇒ Object
Iterates over the tracks.
-
#get_measures ⇒ Object
Returns a Measures object, which is an array container for all measures in the sequence.
-
#initialize ⇒ Sequence
constructor
A new instance of Sequence.
-
#length_to_delta(length) ⇒ Object
Translates
length
(a multiple of a quarter note) into a delta time. -
#name ⇒ Object
Returns the name of the first track (track zero).
-
#name=(name) ⇒ Object
Hands the name to the first track.
-
#note_to_delta(name) ⇒ Object
Given a note length name like “whole”, “dotted quarter”, or “8th triplet”, return the length of that note in quarter notes as a delta time.
-
#note_to_length(name) ⇒ Object
Given a note length name like “whole”, “dotted quarter”, or “8th triplet”, return the length of that note in quarter notes as a floating-point number, suitable for use as an argument to length_to_delta.
-
#pulses_to_seconds(pulses) ⇒ Object
Pulses (also called ticks) are the units of delta times and event time_from_start values.
-
#read(io, &block) ⇒ Object
Reads a MIDI stream.
-
#time_signature(numer, denom, clocks, qnotes) ⇒ Object
Sets the time signature.
-
#write(io, midi_format = 1, &block) ⇒ Object
Writes to a MIDI stream.
Constructor Details
#initialize ⇒ Sequence
Returns a new instance of Sequence.
43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/midilib/sequence.rb', line 43 def initialize @tracks = [] @ppqn = 480 # Time signature @numer = 4 # Numer + denom = 4/4 time default @denom = 2 @clocks = 24 # Bug fix Nov 11, 2007 - this is not the same as ppqn! @qnotes = 8 @reader_class = IO::SeqReader @writer_class = IO::SeqWriter end |
Instance Attribute Details
#clocks ⇒ Object
Returns the value of attribute clocks.
35 36 37 |
# File 'lib/midilib/sequence.rb', line 35 def clocks @clocks end |
#denom ⇒ Object
Returns the value of attribute denom.
35 36 37 |
# File 'lib/midilib/sequence.rb', line 35 def denom @denom end |
#format ⇒ Object
The MIDI file format (0, 1, or 2)
34 35 36 |
# File 'lib/midilib/sequence.rb', line 34 def format @format end |
#numer ⇒ Object
Returns the value of attribute numer.
35 36 37 |
# File 'lib/midilib/sequence.rb', line 35 def numer @numer end |
#ppqn ⇒ Object
Pulses (i.e. clocks) Per Quarter Note resolution for the sequence
32 33 34 |
# File 'lib/midilib/sequence.rb', line 32 def ppqn @ppqn end |
#qnotes ⇒ Object
Returns the value of attribute qnotes.
35 36 37 |
# File 'lib/midilib/sequence.rb', line 35 def qnotes @qnotes end |
#reader_class ⇒ Object
The class to use for reading MIDI from a stream. The default is MIDI::IO::SeqReader. You can change this at any time.
38 39 40 |
# File 'lib/midilib/sequence.rb', line 38 def reader_class @reader_class end |
#tracks ⇒ Object
Array with all tracks for the sequence
30 31 32 |
# File 'lib/midilib/sequence.rb', line 30 def tracks @tracks end |
#writer_class ⇒ Object
The class to use for writeing MIDI from a stream. The default is MIDI::IO::SeqWriter. You can change this at any time.
41 42 43 |
# File 'lib/midilib/sequence.rb', line 41 def writer_class @writer_class end |
Instance Method Details
#beats_per_minute ⇒ Object Also known as: bpm, tempo
Returns the song tempo in beats per minute.
66 67 68 69 70 71 |
# File 'lib/midilib/sequence.rb', line 66 def beats_per_minute return DEFAULT_TEMPO if @tracks.nil? || @tracks.empty? event = @tracks.first.events.detect { |e| e.is_a?(MIDI::Tempo) } event ? Tempo.mpq_to_bpm(event.tempo) : DEFAULT_TEMPO end |
#each(&block) ⇒ Object
Iterates over the tracks.
154 155 156 |
# File 'lib/midilib/sequence.rb', line 154 def each(&block) # :yields: track @tracks.each(&block) end |
#get_measures ⇒ Object
Returns a Measures object, which is an array container for all measures in the sequence
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/midilib/sequence.rb', line 160 def get_measures # Collect time sig events and scan for last event time time_sigs = [] max_pos = 0 @tracks.each do |t| t.each do |e| time_sigs << e if e.is_a?(MIDI::TimeSig) max_pos = e.time_from_start if e.time_from_start > max_pos end end time_sigs.sort { |x, y| x.time_from_start <=> y.time_from_start } # Add a "fake" time sig event at the very last position of the sequence, # just to make sure the whole sequence is calculated. t = MIDI::TimeSig.new(4, 2, 24, 8, 0) t.time_from_start = max_pos time_sigs << t # Default to 4/4 measure_length = @ppqn * 4 oldnumer = 4 olddenom = 2 oldbeats = 24 measures = MIDI::Measures.new(max_pos, @ppqn) curr_pos = 0 curr_meas_no = 1 time_sigs.each do |te| meas_count = (te.time_from_start - curr_pos) / measure_length meas_count += 1 if (te.time_from_start - curr_pos) % measure_length > 0 1.upto(meas_count) do |i| measures << MIDI::Measure.new(curr_meas_no, curr_pos, measure_length, oldnumer, olddenom, oldbeats) curr_meas_no += 1 curr_pos += measure_length end oldnumer = te.numerator olddenom = te.denominator oldbeats = te.metronome_ticks measure_length = te.measure_duration(@ppqn) end measures end |
#length_to_delta(length) ⇒ Object
Translates length
(a multiple of a quarter note) into a delta time. For example, 1 is a quarter note, 1.0/32.0 is a 32nd note, 1.5 is a dotted quarter, etc. Be aware when using division; 1/32 is zero due to integer mathematics and rounding. Use floating-point numbers like 1.0 and 32.0. This method always returns an integer by calling ‘.round` on the floating-point result.
See also note_to_delta and note_to_length.
122 123 124 |
# File 'lib/midilib/sequence.rb', line 122 def length_to_delta(length) (@ppqn * length).round end |
#name ⇒ Object
Returns the name of the first track (track zero). If there are no tracks, returns UNNAMED.
128 129 130 131 132 |
# File 'lib/midilib/sequence.rb', line 128 def name return UNNAMED if @tracks.empty? @tracks.first.name end |
#name=(name) ⇒ Object
Hands the name to the first track. Does nothing if there are no tracks.
135 136 137 138 139 |
# File 'lib/midilib/sequence.rb', line 135 def name=(name) return if @tracks.empty? @tracks.first.name = name end |
#note_to_delta(name) ⇒ Object
Given a note length name like “whole”, “dotted quarter”, or “8th triplet”, return the length of that note in quarter notes as a delta time.
85 86 87 |
# File 'lib/midilib/sequence.rb', line 85 def note_to_delta(name) length_to_delta(note_to_length(name)) end |
#note_to_length(name) ⇒ Object
Given a note length name like “whole”, “dotted quarter”, or “8th triplet”, return the length of that note in quarter notes as a floating-point number, suitable for use as an argument to length_to_delta.
Legal names are any value in NOTE_TO_LENGTH, optionally prefixed by “dotted_” and/or suffixed by “_triplet”. So, for example, “dotted_quarter_triplet” returns the length of a dotted quarter-note triplet and “32nd” returns 1/32.
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/midilib/sequence.rb', line 98 def note_to_length(name) name.strip! name =~ /^(dotted)?(.*?)(triplet)?$/ dotted = Regexp.last_match(1) note_name = Regexp.last_match(2) triplet = Regexp.last_match(3) note_name.strip! mult = 1.0 mult = 1.5 if dotted mult /= 3.0 if triplet len = NOTE_TO_LENGTH[note_name] raise "Sequence.note_to_length: \"#{note_name}\" not understood in \"#{name}\"" unless len len * mult end |
#pulses_to_seconds(pulses) ⇒ Object
Pulses (also called ticks) are the units of delta times and event time_from_start values. This method converts a number of pulses to a float value that is a time in seconds.
78 79 80 |
# File 'lib/midilib/sequence.rb', line 78 def pulses_to_seconds(pulses) (pulses.to_f / @ppqn.to_f / beats_per_minute) * 60.0 end |
#read(io, &block) ⇒ Object
Reads a MIDI stream.
142 143 144 145 |
# File 'lib/midilib/sequence.rb', line 142 def read(io, &block) # :yields: track, num_tracks, index reader = @reader_class.new(self, &block) reader.read_from(io) end |
#time_signature(numer, denom, clocks, qnotes) ⇒ Object
Sets the time signature.
58 59 60 61 62 63 |
# File 'lib/midilib/sequence.rb', line 58 def time_signature(numer, denom, clocks, qnotes) @numer = numer @denom = denom @clocks = clocks @qnotes = qnotes end |
#write(io, midi_format = 1, &block) ⇒ Object
Writes to a MIDI stream. midi_format
defaults to 1.
148 149 150 151 |
# File 'lib/midilib/sequence.rb', line 148 def write(io, midi_format = 1, &block) # :yields: track, num_tracks, index writer = @writer_class.new(self, midi_format, &block) writer.write_to(io) end |