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