class MIDI::IO::SeqWriter
Public Class Methods
new(seq, midi_format = 1) { |num_tracks, index| ... }
click to toggle source
# File lib/midilib/io/seqwriter.rb, line 9 def initialize(seq, midi_format = 1, &block) # :yields: num_tracks, index @seq = seq @midi_format = midi_format || 1 @update_block = block end
Public Instance Methods
possibly_munge_due_to_running_status_byte(data, prev_status)
click to toggle source
If we can use a running status byte, delete the status byte from the given data. Return the status to remember for next time as the running status byte for this event.
# File lib/midilib/io/seqwriter.rb, line 86 def possibly_munge_due_to_running_status_byte(data, prev_status) status = data[0] return status if status >= 0xf0 || prev_status >= 0xf0 chan = (status & 0x0f) return status if chan != (prev_status & 0x0f) status = (status & 0xf0) prev_status = (prev_status & 0xf0) # Both events are on the same channel. If the two status bytes are # exactly the same, the rest is trivial. If it's note on/note off, # we can combine those further. if status == prev_status data[0, 1] = [] # delete status byte from data status + chan elsif status == NOTE_OFF && data[2] == 64 # If we see a note off and the velocity is 64, we can store # a note on with a velocity of 0. If the velocity isn't 64 # then storing a note on would be bad because the would be # changed to 64 when reading the file back in. data[2] = 0 # set vel to 0; do before possible shrinking status = NOTE_ON + chan if prev_status == NOTE_ON data[0, 1] = [] # delete status byte else data[0] = status end status else # Can't compress data status + chan end end
write16(val)
click to toggle source
# File lib/midilib/io/seqwriter.rb, line 135 def write16(val) val = (-val | 0x8000) if val < 0 @io.putc((val >> 8) & 0xff) @io.putc(val & 0xff) @bytes_written += 2 end
write32(val)
click to toggle source
# File lib/midilib/io/seqwriter.rb, line 143 def write32(val) val = (-val | 0x80000000) if val < 0 @io.putc((val >> 24) & 0xff) @io.putc((val >> 16) & 0xff) @io.putc((val >> 8) & 0xff) @io.putc(val & 0xff) @bytes_written += 4 end
write_bytes(bytes)
click to toggle source
# File lib/midilib/io/seqwriter.rb, line 153 def write_bytes(bytes) bytes.each { |b| @io.putc(b) } bytes.length end
write_header()
click to toggle source
# File lib/midilib/io/seqwriter.rb, line 38 def write_header @io.print 'MThd' write32(6) write16(@midi_format) # Ignore sequence format; write as format 1 or 0, default 1 write16(@seq.tracks.length) write16(@seq.ppqn) end
write_instrument(instrument)
click to toggle source
# File lib/midilib/io/seqwriter.rb, line 121 def write_instrument(instrument) return if instrument.nil? event = MetaEvent.new(META_INSTRUMENT, instrument) write_var_len(0) data = event.data_as_bytes @bytes_written += write_bytes(data) end
write_to(io)
click to toggle source
Writes a MIDI
format 1 file.
# File lib/midilib/io/seqwriter.rb, line 16 def write_to(io) if @midi_format == 0 # merge tracks before writing merged_seq = Sequence.new merged_track = Track.new(merged_seq) merged_seq.tracks << merged_track @seq.each do |track| merged_track.merge(track.events) end @seq = merged_seq # replace end @io = io @bytes_written = 0 write_header @update_block.call(nil, @seq.tracks.length, 0) if @update_block @seq.tracks.each_with_index do |track, i| write_track(track) @update_block.call(track, @seq.tracks.length, i) if @update_block end end
write_track(track)
click to toggle source
# File lib/midilib/io/seqwriter.rb, line 46 def write_track(track) @io.print 'MTrk' track_size_file_pos = @io.tell write32(0) # Dummy byte count; overwritten later @bytes_written = 0 # Reset after previous write write_instrument(track.instrument) prev_status = 0 track.events.each do |event| write_var_len(event.delta_time) unless event.is_a?(Realtime) data = event.data_as_bytes status = data[0] # status byte plus channel number, if any # running status byte status = possibly_munge_due_to_running_status_byte(data, prev_status) @bytes_written += write_bytes(data) prev_status = status end # Write track end event if the track doesn't have one. unless track.events.last.is_a?(MetaEvent) && track.events.last.meta_type == META_TRACK_END event = MetaEvent.new(META_TRACK_END) write_var_len(0) @bytes_written += write_bytes(event.data_as_bytes) end # Go back to beginning of track data and write number of bytes, # then come back here to end of file. @io.seek(track_size_file_pos) write32(@bytes_written) @io.seek(0, ::IO::SEEK_END) end
write_var_len(val)
click to toggle source
# File lib/midilib/io/seqwriter.rb, line 130 def write_var_len(val) buffer = Utils.as_var_len(val) @bytes_written += write_bytes(buffer) end