class MIDI::IO::SeqReader
Reads MIDI
files. As a subclass of MIDIFile
, this class implements the callback methods for each MIDI
event and use them to build Track
and Event
objects and give the tracks to a Sequence
.
Ensures that each track ends with an end of track meta event, and that Track#recalc_times
is called at the end of the track so it can update each event with its time from the track’s start (see end_track
below).
Public Class Methods
new(seq) { |track, num_tracks, index| ... }
click to toggle source
The optional &block is called once at the start of the file and again at the end of each track. There are three arguments to the block: the track, the track number (1 through n), and the total number of tracks.
Calls superclass method
MIDI::IO::MIDIFile::new
# File lib/midilib/io/seqreader.rb, line 19 def initialize(seq, &block) # :yields: track, num_tracks, index super() @seq = seq @track = nil @chan_mask = 0 @update_block = block end
Public Instance Methods
chan_pressure(chan, press)
click to toggle source
# File lib/midilib/io/seqreader.rb, line 127 def chan_pressure(chan, press) @track.events << ChannelPressure.new(chan, press, @curr_ticks) track_uses_channel(chan) end
controller(chan, control, value)
click to toggle source
# File lib/midilib/io/seqreader.rb, line 112 def controller(chan, control, value) @track.events << Controller.new(chan, control, value, @curr_ticks) track_uses_channel(chan) end
end_track()
click to toggle source
# File lib/midilib/io/seqreader.rb, line 42 def end_track # Turn off any pending note on messages @pending.each { |on| make_note_off(on, 64) } @pending = nil # Make sure track has an end of track event and that all of the # `time_from_start` values are correct. @track.ensure_track_end_meta_event @track.recalc_times # Store bitmask of all channels used into track @track.channels_used = @chan_mask # call update block @update_block.call(@track, @ntrks, @seq.tracks.length) if @update_block end
eot()
click to toggle source
# File lib/midilib/io/seqreader.rb, line 136 def eot @track.events << MetaEvent.new(META_TRACK_END, nil, @curr_ticks) end
header(format, ntrks, division)
click to toggle source
# File lib/midilib/io/seqreader.rb, line 27 def header(format, ntrks, division) @seq.format = format @seq.ppqn = division @ntrks = ntrks @update_block.call(nil, @ntrks, 0) if @update_block end
key_signature(sharpflat, is_minor)
click to toggle source
# File lib/midilib/io/seqreader.rb, line 179 def key_signature(sharpflat, is_minor) @track.events << KeySig.new(sharpflat, is_minor, @curr_ticks) end
make_note_off(on, vel)
click to toggle source
# File lib/midilib/io/seqreader.rb, line 100 def make_note_off(on, vel) off = NoteOff.new(on.channel, on.note, vel, @curr_ticks) @track.events << off on.off = off off.on = on end
meta_misc(type, msg)
click to toggle source
# File lib/midilib/io/seqreader.rb, line 140 def meta_misc(type, msg) @track.events << MetaEvent.new(type, msg, @curr_ticks) end
note_off(chan, note, vel)
click to toggle source
# File lib/midilib/io/seqreader.rb, line 71 def note_off(chan, note, vel) # Find note on, create note off, connect the two, and remove # note on from pending list. corresp_note_on = nil @pending.each_with_index do |on, i| next unless on.note == note && on.channel == chan @pending.delete_at(i) corresp_note_on = on break end if corresp_note_on make_note_off(corresp_note_on, vel) else # When a corresponding note on is missing, # keep note off as input with lefting on/off attr to nil. off = NoteOff.new(chan, note, vel, @curr_ticks) @track.events << off if $DEBUG warn "note off with no earlier note on (ch #{chan}, note" + " #{note}, vel #{vel})" end end end
note_on(chan, note, vel)
click to toggle source
# File lib/midilib/io/seqreader.rb, line 59 def note_on(chan, note, vel) if vel == 0 note_off(chan, note, 64) return end on = NoteOn.new(chan, note, vel, @curr_ticks) @track.events << on @pending << on track_uses_channel(chan) end
pitch_bend(chan, lsb, msb)
click to toggle source
# File lib/midilib/io/seqreader.rb, line 117 def pitch_bend(chan, lsb, msb) @track.events << PitchBend.new(chan, (msb << 7) + lsb, @curr_ticks) track_uses_channel(chan) end
pressure(chan, note, press)
click to toggle source
# File lib/midilib/io/seqreader.rb, line 107 def pressure(chan, note, press) @track.events << PolyPressure.new(chan, note, press, @curr_ticks) track_uses_channel(chan) end
program(chan, program)
click to toggle source
# File lib/midilib/io/seqreader.rb, line 122 def program(chan, program) @track.events << ProgramChange.new(chan, program, @curr_ticks) track_uses_channel(chan) end
start_track()
click to toggle source
# File lib/midilib/io/seqreader.rb, line 35 def start_track @track = Track.new(@seq) @seq.tracks << @track @pending = [] end
sysex(msg)
click to toggle source
# File lib/midilib/io/seqreader.rb, line 132 def sysex(msg) @track.events << SystemExclusive.new(msg, @curr_ticks) end
tempo(microsecs)
click to toggle source
–
def smpte(hour, min, sec, frame, fract) end
++
# File lib/midilib/io/seqreader.rb, line 175 def tempo(microsecs) @track.events << Tempo.new(microsecs, @curr_ticks) end
text(type, msg)
click to toggle source
def sequence_number(num) end
++
# File lib/midilib/io/seqreader.rb, line 152 def text(type, msg) case type when META_TEXT, META_LYRIC, META_CUE, META_SEQ_NAME, META_COPYRIGHT @track.events << MetaEvent.new(type, msg, @curr_ticks) when META_INSTRUMENT @track.instrument = msg when META_MARKER @track.events << Marker.new(msg, @curr_ticks) else warn "text = #{msg}, type = #{type}" if $DEBUG end end
time_signature(numer, denom, clocks, qnotes)
click to toggle source
# File lib/midilib/io/seqreader.rb, line 165 def time_signature(numer, denom, clocks, qnotes) @seq.time_signature(numer, denom, clocks, qnotes) @track.events << TimeSig.new(numer, denom, clocks, qnotes, @curr_ticks) end
track_uses_channel(chan)
click to toggle source
Return true if the current track uses the specified channel.
# File lib/midilib/io/seqreader.rb, line 189 def track_uses_channel(chan) @chan_mask |= (1 << chan) end