midilib 2.0.4 → 2.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.rdoc +9 -4
- data/Rakefile +2 -6
- data/examples/from_scratch.rb +3 -5
- data/examples/measures_mbt.rb +4 -4
- data/examples/print_program_changes.rb +9 -9
- data/examples/reader2text.rb +188 -188
- data/examples/seq2text.rb +17 -17
- data/examples/split.rb +19 -19
- data/examples/strings.rb +14 -14
- data/examples/transpose.rb +31 -31
- data/html/IO.html +65 -169
- data/html/MIDI.html +138 -256
- data/html/MIDI/ActiveSense.html +89 -178
- data/html/MIDI/ChannelEvent.html +95 -183
- data/html/MIDI/ChannelPressure.html +105 -190
- data/html/MIDI/Clock.html +89 -178
- data/html/MIDI/Continue.html +89 -178
- data/html/MIDI/Controller.html +107 -192
- data/html/MIDI/Event.html +138 -222
- data/html/MIDI/IO.html +45 -157
- data/html/MIDI/IO/MIDIFile.html +596 -568
- data/html/MIDI/IO/SeqReader.html +272 -314
- data/html/MIDI/IO/SeqWriter.html +229 -305
- data/html/MIDI/KeySig.html +129 -211
- data/html/MIDI/MIDI.html +45 -154
- data/html/MIDI/MIDI/MIDI.html +45 -154
- data/html/MIDI/MIDI/MIDI/Array.html +87 -185
- data/html/MIDI/Marker.html +71 -170
- data/html/MIDI/Measure.html +95 -190
- data/html/MIDI/Measures.html +103 -193
- data/html/MIDI/MetaEvent.html +180 -253
- data/html/MIDI/NoteEvent.html +118 -204
- data/html/MIDI/NoteOff.html +95 -183
- data/html/MIDI/NoteOn.html +95 -183
- data/html/MIDI/PitchBend.html +106 -191
- data/html/MIDI/PolyPressure.html +106 -189
- data/html/MIDI/ProgramChange.html +105 -190
- data/html/MIDI/Realtime.html +98 -184
- data/html/MIDI/Sequence.html +246 -311
- data/html/MIDI/SongPointer.html +106 -191
- data/html/MIDI/SongSelect.html +105 -190
- data/html/MIDI/Start.html +89 -178
- data/html/MIDI/Stop.html +89 -178
- data/html/MIDI/SystemCommon.html +71 -170
- data/html/MIDI/SystemExclusive.html +108 -193
- data/html/MIDI/SystemReset.html +89 -178
- data/html/MIDI/Tempo.html +135 -213
- data/html/MIDI/TimeSig.html +135 -214
- data/html/MIDI/Track.html +217 -291
- data/html/MIDI/TuneRequest.html +98 -184
- data/html/MIDI/Utils.html +89 -189
- data/html/README_rdoc.html +237 -257
- data/html/TODO_rdoc.html +64 -139
- data/html/created.rid +14 -14
- data/html/css/fonts.css +167 -0
- data/html/{rdoc.css → css/rdoc.css} +265 -218
- data/html/fonts/Lato-Light.ttf +0 -0
- data/html/fonts/Lato-LightItalic.ttf +0 -0
- data/html/fonts/Lato-Regular.ttf +0 -0
- data/html/fonts/Lato-RegularItalic.ttf +0 -0
- data/html/fonts/SourceCodePro-Bold.ttf +0 -0
- data/html/fonts/SourceCodePro-Regular.ttf +0 -0
- data/html/images/add.png +0 -0
- data/html/images/arrow_up.png +0 -0
- data/html/images/delete.png +0 -0
- data/html/images/tag_blue.png +0 -0
- data/html/index.html +187 -169
- data/html/js/darkfish.js +41 -33
- data/html/js/jquery.js +4 -18
- data/html/js/navigation.js.gz +0 -0
- data/html/js/search.js +20 -5
- data/html/js/search_index.js +1 -1
- data/html/js/search_index.js.gz +0 -0
- data/html/js/searcher.js.gz +0 -0
- data/html/table_of_contents.html +1111 -498
- data/install.rb +43 -32
- data/lib/midilib/consts.rb +407 -407
- data/lib/midilib/event.rb +295 -294
- data/lib/midilib/info.rb +5 -5
- data/lib/midilib/io/midifile.rb +266 -267
- data/lib/midilib/io/seqreader.rb +106 -106
- data/lib/midilib/io/seqwriter.rb +59 -60
- data/lib/midilib/measure.rb +69 -69
- data/lib/midilib/sequence.rb +68 -70
- data/lib/midilib/track.rb +96 -102
- data/lib/midilib/utils.rb +15 -15
- data/test/event_equality.rb +50 -50
- data/test/test_event.rb +120 -122
- data/test/test_io.rb +35 -48
- data/test/test_sequence.rb +60 -60
- data/test/test_track.rb +154 -154
- data/test/test_varlen.rb +23 -25
- metadata +65 -57
    
        data/lib/midilib/io/seqreader.rb
    CHANGED
    
    | @@ -4,54 +4,54 @@ require 'midilib/event' | |
| 4 4 |  | 
| 5 5 | 
             
            module MIDI
         | 
| 6 6 |  | 
| 7 | 
            -
            module IO
         | 
| 8 | 
            -
             | 
| 9 | 
            -
            # Reads MIDI files. As a subclass of MIDIFile, this class implements
         | 
| 10 | 
            -
            #  | 
| 11 | 
            -
            #  | 
| 12 | 
            -
            #
         | 
| 13 | 
            -
            # We append new events to the end of a track's event list, bypassing a | 
| 14 | 
            -
            # to Track.#add. This means that we must call Track.recalc_times at | 
| 15 | 
            -
            # of the track so it can update each event with its time from | 
| 16 | 
            -
            # start (see end_track below).
         | 
| 17 | 
            -
            #
         | 
| 18 | 
            -
            # META_TRACK_END events are not added to tracks. This way, we don't have | 
| 19 | 
            -
            # worry about making sure the last event is always a track end event. | 
| 20 | 
            -
            # rely on the SeqWriter to append a META_TRACK_END event to each | 
| 21 | 
            -
            # it is output.
         | 
| 22 | 
            -
             | 
| 23 | 
            -
            class SeqReader < MIDIFile
         | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 7 | 
            +
              module IO
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                # Reads MIDI files. As a subclass of MIDIFile, this class implements the
         | 
| 10 | 
            +
                # callback methods for each MIDI event and use them to build Track and
         | 
| 11 | 
            +
                # Event objects and give the tracks to a Sequence.
         | 
| 12 | 
            +
                #
         | 
| 13 | 
            +
                # We append new events to the end of a track's event list, bypassing a
         | 
| 14 | 
            +
                # call to Track.#add. This means that we must call Track.recalc_times at
         | 
| 15 | 
            +
                # the end of the track so it can update each event with its time from
         | 
| 16 | 
            +
                # the track's start (see end_track below).
         | 
| 17 | 
            +
                #
         | 
| 18 | 
            +
                # META_TRACK_END events are not added to tracks. This way, we don't have
         | 
| 19 | 
            +
                # to worry about making sure the last event is always a track end event.
         | 
| 20 | 
            +
                # We rely on the SeqWriter to append a META_TRACK_END event to each
         | 
| 21 | 
            +
                # track when it is output.
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                class SeqReader < MIDIFile
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  # The optional proc block is called once at the start of the file and
         | 
| 26 | 
            +
                  # again at the end of each track. There are three arguments to the
         | 
| 27 | 
            +
                  # block: the track, the track number (1 through _n_), and the total
         | 
| 28 | 
            +
                  # number of tracks.
         | 
| 29 | 
            +
                  def initialize(seq, proc = nil) # :yields: track, num_tracks, index
         | 
| 30 30 | 
             
            	super()
         | 
| 31 31 | 
             
            	@seq = seq
         | 
| 32 32 | 
             
            	@track = nil
         | 
| 33 33 | 
             
            	@chan_mask = 0
         | 
| 34 34 | 
             
            	@update_block = block_given?() ? Proc.new() : proc
         | 
| 35 | 
            -
             | 
| 35 | 
            +
                  end
         | 
| 36 36 |  | 
| 37 | 
            -
             | 
| 37 | 
            +
                  def header(format, ntrks, division)
         | 
| 38 38 | 
             
            	@seq.format = format
         | 
| 39 39 | 
             
            	@seq.ppqn = division
         | 
| 40 40 |  | 
| 41 41 | 
             
            	@ntrks = ntrks
         | 
| 42 42 | 
             
            	@update_block.call(nil, @ntrks, 0) if @update_block
         | 
| 43 | 
            -
             | 
| 43 | 
            +
                  end
         | 
| 44 44 |  | 
| 45 | 
            -
             | 
| 45 | 
            +
                  def start_track()
         | 
| 46 46 | 
             
            	@track = Track.new(@seq)
         | 
| 47 47 | 
             
            	@seq.tracks << @track
         | 
| 48 48 |  | 
| 49 49 | 
             
            	@pending = []
         | 
| 50 | 
            -
             | 
| 50 | 
            +
                  end
         | 
| 51 51 |  | 
| 52 | 
            -
             | 
| 52 | 
            +
                  def end_track()
         | 
| 53 53 | 
             
            	# Turn off any pending note on messages
         | 
| 54 | 
            -
            	@pending.each { | | 
| 54 | 
            +
            	@pending.each { |on| make_note_off(on, 64) }
         | 
| 55 55 | 
             
            	@pending = nil
         | 
| 56 56 |  | 
| 57 57 | 
             
            	# Don't bother adding the META_TRACK_END event to the track.
         | 
| @@ -67,136 +67,136 @@ class SeqReader < MIDIFile | |
| 67 67 |  | 
| 68 68 | 
             
            	# call update block
         | 
| 69 69 | 
             
            	@update_block.call(@track, @ntrks, @seq.tracks.length) if @update_block
         | 
| 70 | 
            -
             | 
| 70 | 
            +
                  end
         | 
| 71 71 |  | 
| 72 | 
            -
             | 
| 72 | 
            +
                  def note_on(chan, note, vel)
         | 
| 73 73 | 
             
            	if vel == 0
         | 
| 74 | 
            -
             | 
| 75 | 
            -
             | 
| 74 | 
            +
                      note_off(chan, note, 64)
         | 
| 75 | 
            +
                      return
         | 
| 76 76 | 
             
            	end
         | 
| 77 77 |  | 
| 78 78 | 
             
            	on = NoteOn.new(chan, note, vel, @curr_ticks)
         | 
| 79 79 | 
             
            	@track.events << on
         | 
| 80 80 | 
             
            	@pending << on
         | 
| 81 81 | 
             
            	track_uses_channel(chan)
         | 
| 82 | 
            -
             | 
| 82 | 
            +
                  end
         | 
| 83 83 |  | 
| 84 | 
            -
             | 
| 84 | 
            +
                  def note_off(chan, note, vel)
         | 
| 85 85 | 
             
            	# Find note on, create note off, connect the two, and remove
         | 
| 86 86 | 
             
            	# note on from pending list.
         | 
| 87 | 
            -
            	@pending.each_with_index  | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
            	 | 
| 87 | 
            +
            	@pending.each_with_index do |on, i|
         | 
| 88 | 
            +
                      if on.note == note && on.channel == chan
         | 
| 89 | 
            +
                        make_note_off(on, vel)
         | 
| 90 | 
            +
                        @pending.delete_at(i)
         | 
| 91 | 
            +
                        return
         | 
| 92 | 
            +
                      end
         | 
| 93 | 
            +
            	end
         | 
| 94 94 | 
             
            	$stderr.puts "note off with no earlier note on (ch #{chan}, note" +
         | 
| 95 | 
            -
             | 
| 96 | 
            -
             | 
| 95 | 
            +
                      " #{note}, vel #{vel})" if $DEBUG
         | 
| 96 | 
            +
                  end
         | 
| 97 97 |  | 
| 98 | 
            -
             | 
| 98 | 
            +
                  def make_note_off(on, vel)
         | 
| 99 99 | 
             
            	off = NoteOff.new(on.channel, on.note, vel, @curr_ticks)
         | 
| 100 100 | 
             
            	@track.events << off
         | 
| 101 101 | 
             
            	on.off = off
         | 
| 102 102 | 
             
            	off.on = on
         | 
| 103 | 
            -
             | 
| 103 | 
            +
                  end
         | 
| 104 104 |  | 
| 105 | 
            -
             | 
| 105 | 
            +
                  def pressure(chan, note, press)
         | 
| 106 106 | 
             
            	@track.events << PolyPressure.new(chan, note, press, @curr_ticks)
         | 
| 107 107 | 
             
            	track_uses_channel(chan)
         | 
| 108 | 
            -
             | 
| 108 | 
            +
                  end
         | 
| 109 109 |  | 
| 110 | 
            -
             | 
| 110 | 
            +
                  def controller(chan, control, value)
         | 
| 111 111 | 
             
            	@track.events << Controller.new(chan, control, value, @curr_ticks)
         | 
| 112 112 | 
             
            	track_uses_channel(chan)
         | 
| 113 | 
            -
             | 
| 113 | 
            +
                  end
         | 
| 114 114 |  | 
| 115 | 
            -
             | 
| 115 | 
            +
                  def pitch_bend(chan, lsb, msb)
         | 
| 116 116 | 
             
            	@track.events << PitchBend.new(chan, (msb << 7) + lsb, @curr_ticks)
         | 
| 117 117 | 
             
            	track_uses_channel(chan)
         | 
| 118 | 
            -
             | 
| 118 | 
            +
                  end
         | 
| 119 119 |  | 
| 120 | 
            -
             | 
| 120 | 
            +
                  def program(chan, program)
         | 
| 121 121 | 
             
            	@track.events << ProgramChange.new(chan, program, @curr_ticks)
         | 
| 122 122 | 
             
            	track_uses_channel(chan)
         | 
| 123 | 
            -
             | 
| 123 | 
            +
                  end
         | 
| 124 124 |  | 
| 125 | 
            -
             | 
| 125 | 
            +
                  def chan_pressure(chan, press)
         | 
| 126 126 | 
             
            	@track.events << ChannelPressure.new(chan, press, @curr_ticks)
         | 
| 127 127 | 
             
            	track_uses_channel(chan)
         | 
| 128 | 
            -
             | 
| 128 | 
            +
                  end
         | 
| 129 129 |  | 
| 130 | 
            -
             | 
| 130 | 
            +
                  def sysex(msg)
         | 
| 131 131 | 
             
            	@track.events << SystemExclusive.new(msg, @curr_ticks)
         | 
| 132 | 
            -
             | 
| 132 | 
            +
                  end
         | 
| 133 133 |  | 
| 134 | 
            -
             | 
| 134 | 
            +
                  def meta_misc(type, msg)
         | 
| 135 135 | 
             
            	@track.events << MetaEvent.new(type, msg, @curr_ticks)
         | 
| 136 | 
            -
             | 
| 136 | 
            +
                  end
         | 
| 137 137 |  | 
| 138 | 
            -
            # --
         | 
| 139 | 
            -
            #      def sequencer_specific(type, msg)
         | 
| 140 | 
            -
            #      end
         | 
| 138 | 
            +
                  # --
         | 
| 139 | 
            +
                  #      def sequencer_specific(type, msg)
         | 
| 140 | 
            +
                  #      end
         | 
| 141 141 |  | 
| 142 | 
            -
            #      def sequence_number(num)
         | 
| 143 | 
            -
            #      end
         | 
| 144 | 
            -
            # ++
         | 
| 142 | 
            +
                  #      def sequence_number(num)
         | 
| 143 | 
            +
                  #      end
         | 
| 144 | 
            +
                  # ++
         | 
| 145 145 |  | 
| 146 | 
            -
             | 
| 146 | 
            +
                  def text(type, msg)
         | 
| 147 147 | 
             
            	case type
         | 
| 148 148 | 
             
                    when META_TEXT, META_LYRIC, META_CUE
         | 
| 149 | 
            -
             | 
| 149 | 
            +
                      @track.events << MetaEvent.new(type, msg, @curr_ticks)
         | 
| 150 150 | 
             
            	when META_SEQ_NAME, META_COPYRIGHT
         | 
| 151 | 
            -
             | 
| 152 | 
            -
            	when META_INSTRUMENT | 
| 153 | 
            -
             | 
| 151 | 
            +
                      @track.events << MetaEvent.new(type, msg, 0)
         | 
| 152 | 
            +
            	when META_INSTRUMENT
         | 
| 153 | 
            +
                      @track.instrument = msg
         | 
| 154 154 | 
             
            	when META_MARKER
         | 
| 155 | 
            -
             | 
| 155 | 
            +
                      @track.events << Marker.new(msg, @curr_ticks)
         | 
| 156 156 | 
             
            	else
         | 
| 157 | 
            -
             | 
| 157 | 
            +
                      $stderr.puts "text = #{msg}, type = #{type}" if $DEBUG
         | 
| 158 158 | 
             
            	end
         | 
| 159 | 
            -
             | 
| 160 | 
            -
             | 
| 161 | 
            -
            # --
         | 
| 162 | 
            -
             | 
| 163 | 
            -
             | 
| 164 | 
            -
             | 
| 165 | 
            -
             | 
| 166 | 
            -
            #  	def eot()
         | 
| 167 | 
            -
            #  	    @track.events << MetaEvent.new(META_TRACK_END, nil, @curr_ticks)
         | 
| 168 | 
            -
            #  	end
         | 
| 169 | 
            -
            # ++
         | 
| 170 | 
            -
             | 
| 171 | 
            -
             | 
| 159 | 
            +
                  end
         | 
| 160 | 
            +
             | 
| 161 | 
            +
                  # --
         | 
| 162 | 
            +
                  # Don't bother adding the META_TRACK_END event to the track. This way,
         | 
| 163 | 
            +
                  # we don't have to worry about always making sure the last event is
         | 
| 164 | 
            +
                  # always a track end event. We just have to make sure to write one when
         | 
| 165 | 
            +
                  # the track is output back to a file.
         | 
| 166 | 
            +
                  #  	def eot()
         | 
| 167 | 
            +
                  #  	    @track.events << MetaEvent.new(META_TRACK_END, nil, @curr_ticks)
         | 
| 168 | 
            +
                  #  	end
         | 
| 169 | 
            +
                  # ++
         | 
| 170 | 
            +
             | 
| 171 | 
            +
                  def time_signature(numer, denom, clocks, qnotes)
         | 
| 172 172 | 
             
            	@seq.time_signature(numer, denom, clocks, qnotes)
         | 
| 173 173 | 
             
                    @track.events << TimeSig.new(numer, denom, clocks, qnotes, @curr_ticks)
         | 
| 174 | 
            -
             | 
| 174 | 
            +
                  end
         | 
| 175 175 |  | 
| 176 | 
            -
            # --
         | 
| 177 | 
            -
            #      def smpte(hour, min, sec, frame, fract)
         | 
| 178 | 
            -
            #      end
         | 
| 179 | 
            -
            # ++
         | 
| 176 | 
            +
                  # --
         | 
| 177 | 
            +
                  #      def smpte(hour, min, sec, frame, fract)
         | 
| 178 | 
            +
                  #      end
         | 
| 179 | 
            +
                  # ++
         | 
| 180 180 |  | 
| 181 | 
            -
             | 
| 181 | 
            +
                  def tempo(microsecs)
         | 
| 182 182 | 
             
            	@track.events << Tempo.new(microsecs, @curr_ticks)
         | 
| 183 | 
            -
             | 
| 183 | 
            +
                  end
         | 
| 184 184 |  | 
| 185 | 
            -
             | 
| 186 | 
            -
             | 
| 187 | 
            -
             | 
| 185 | 
            +
                  def key_signature(sharpflat, is_minor)
         | 
| 186 | 
            +
                    @track.events << KeySig.new(sharpflat, is_minor, @curr_ticks)
         | 
| 187 | 
            +
                  end
         | 
| 188 188 |  | 
| 189 | 
            -
            # --
         | 
| 190 | 
            -
            #      def arbitrary(msg)
         | 
| 191 | 
            -
            #      end
         | 
| 192 | 
            -
            # ++
         | 
| 189 | 
            +
                  # --
         | 
| 190 | 
            +
                  #      def arbitrary(msg)
         | 
| 191 | 
            +
                  #      end
         | 
| 192 | 
            +
                  # ++
         | 
| 193 193 |  | 
| 194 | 
            -
             | 
| 195 | 
            -
             | 
| 194 | 
            +
                  # Return true if the current track uses the specified channel.
         | 
| 195 | 
            +
                  def track_uses_channel(chan)
         | 
| 196 196 | 
             
            	@chan_mask = @chan_mask | (1 << chan)
         | 
| 197 | 
            -
             | 
| 197 | 
            +
                  end
         | 
| 198 198 |  | 
| 199 | 
            -
            end
         | 
| 199 | 
            +
                end
         | 
| 200 200 |  | 
| 201 | 
            -
            end
         | 
| 201 | 
            +
              end
         | 
| 202 202 | 
             
            end
         | 
    
        data/lib/midilib/io/seqwriter.rb
    CHANGED
    
    | @@ -5,36 +5,36 @@ require 'midilib/utils' | |
| 5 5 |  | 
| 6 6 | 
             
            module MIDI
         | 
| 7 7 |  | 
| 8 | 
            -
            module IO
         | 
| 8 | 
            +
              module IO
         | 
| 9 9 |  | 
| 10 | 
            -
            class SeqWriter
         | 
| 10 | 
            +
                class SeqWriter
         | 
| 11 11 |  | 
| 12 | 
            -
             | 
| 12 | 
            +
                  def initialize(seq, proc = nil) # :yields: num_tracks, index
         | 
| 13 13 | 
             
            	@seq = seq
         | 
| 14 14 | 
             
            	@update_block = block_given?() ? Proc.new() : proc
         | 
| 15 | 
            -
             | 
| 15 | 
            +
                  end
         | 
| 16 16 |  | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 17 | 
            +
                  # Writes a MIDI format 1 file.
         | 
| 18 | 
            +
                  def write_to(io)
         | 
| 19 19 | 
             
            	@io = io
         | 
| 20 20 | 
             
            	@bytes_written = 0
         | 
| 21 21 | 
             
            	write_header()
         | 
| 22 22 | 
             
            	@update_block.call(nil, @seq.tracks.length, 0) if @update_block
         | 
| 23 | 
            -
            	@seq.tracks.each_with_index  | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
            	 | 
| 27 | 
            -
             | 
| 23 | 
            +
            	@seq.tracks.each_with_index do |track, i|
         | 
| 24 | 
            +
                      write_track(track)
         | 
| 25 | 
            +
                      @update_block.call(track, @seq.tracks.length, i) if @update_block
         | 
| 26 | 
            +
            	end
         | 
| 27 | 
            +
                  end
         | 
| 28 28 |  | 
| 29 | 
            -
             | 
| 29 | 
            +
                  def write_header
         | 
| 30 30 | 
             
            	@io.print 'MThd'
         | 
| 31 31 | 
             
            	write32(6)
         | 
| 32 32 | 
             
            	write16(1)		# Ignore sequence format; write as format 1
         | 
| 33 33 | 
             
            	write16(@seq.tracks.length)
         | 
| 34 34 | 
             
            	write16(@seq.ppqn)
         | 
| 35 | 
            -
             | 
| 35 | 
            +
                  end
         | 
| 36 36 |  | 
| 37 | 
            -
             | 
| 37 | 
            +
                  def write_track(track)
         | 
| 38 38 | 
             
            	@io.print 'MTrk'
         | 
| 39 39 | 
             
            	track_size_file_pos = @io.tell()
         | 
| 40 40 | 
             
            	write32(0)		# Dummy byte count; overwritten later
         | 
| @@ -44,23 +44,22 @@ class SeqWriter | |
| 44 44 |  | 
| 45 45 | 
             
            	prev_event = nil
         | 
| 46 46 | 
             
            	prev_status = 0
         | 
| 47 | 
            -
            	track.events.each  | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 47 | 
            +
            	track.events.each do |event|
         | 
| 48 | 
            +
                      if !event.kind_of?(Realtime)
         | 
| 49 | 
            +
                        write_var_len(event.delta_time)
         | 
| 50 | 
            +
                      end
         | 
| 51 51 |  | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 52 | 
            +
                      data = event.data_as_bytes()
         | 
| 53 | 
            +
                      status = data[0] # status byte plus channel number, if any
         | 
| 54 54 |  | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
            							       prev_status)
         | 
| 55 | 
            +
                      # running status byte
         | 
| 56 | 
            +
                      status = possibly_munge_due_to_running_status_byte(data, prev_status)
         | 
| 58 57 |  | 
| 59 | 
            -
             | 
| 58 | 
            +
                      @bytes_written += write_bytes(data)
         | 
| 60 59 |  | 
| 61 | 
            -
             | 
| 62 | 
            -
             | 
| 63 | 
            -
            	 | 
| 60 | 
            +
                      prev_event = event
         | 
| 61 | 
            +
                      prev_status = status
         | 
| 62 | 
            +
            	end
         | 
| 64 63 |  | 
| 65 64 | 
             
            	# Write track end event.
         | 
| 66 65 | 
             
            	event = MetaEvent.new(META_TRACK_END)
         | 
| @@ -72,12 +71,12 @@ class SeqWriter | |
| 72 71 | 
             
            	@io.seek(track_size_file_pos)
         | 
| 73 72 | 
             
            	write32(@bytes_written)
         | 
| 74 73 | 
             
            	@io.seek(0, ::IO::SEEK_END)
         | 
| 75 | 
            -
             | 
| 74 | 
            +
                  end
         | 
| 76 75 |  | 
| 77 | 
            -
             | 
| 78 | 
            -
             | 
| 79 | 
            -
             | 
| 80 | 
            -
             | 
| 76 | 
            +
                  # If we can use a running status byte, delete the status byte from
         | 
| 77 | 
            +
                  # the given data. Return the status to remember for next time as the
         | 
| 78 | 
            +
                  # running status byte for this event.
         | 
| 79 | 
            +
                  def possibly_munge_due_to_running_status_byte(data, prev_status)
         | 
| 81 80 | 
             
            	status = data[0]
         | 
| 82 81 | 
             
            	return status if status >= 0xf0 || prev_status >= 0xf0
         | 
| 83 82 |  | 
| @@ -91,49 +90,49 @@ class SeqWriter | |
| 91 90 | 
             
            	# exactly the same, the rest is trivial. If it's note on/note off,
         | 
| 92 91 | 
             
            	# we can combine those further.
         | 
| 93 92 | 
             
            	if status == prev_status
         | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 93 | 
            +
                      data[0,1] = []	# delete status byte from data
         | 
| 94 | 
            +
                      return status + chan
         | 
| 96 95 | 
             
            	elsif status == NOTE_OFF && data[2] == 64
         | 
| 97 | 
            -
             | 
| 98 | 
            -
             | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 102 | 
            -
             | 
| 103 | 
            -
             | 
| 104 | 
            -
             | 
| 105 | 
            -
             | 
| 106 | 
            -
             | 
| 107 | 
            -
             | 
| 108 | 
            -
             | 
| 96 | 
            +
                      # If we see a note off and the velocity is 64, we can store
         | 
| 97 | 
            +
                      # a note on with a velocity of 0. If the velocity isn't 64
         | 
| 98 | 
            +
                      # then storing a note on would be bad because the would be
         | 
| 99 | 
            +
                      # changed to 64 when reading the file back in.
         | 
| 100 | 
            +
                      data[2] = 0		# set vel to 0; do before possible shrinking
         | 
| 101 | 
            +
                      status = NOTE_ON + chan
         | 
| 102 | 
            +
                      if prev_status == NOTE_ON
         | 
| 103 | 
            +
                        data[0,1] = []	# delete status byte
         | 
| 104 | 
            +
                      else
         | 
| 105 | 
            +
                        data[0] = status
         | 
| 106 | 
            +
                      end
         | 
| 107 | 
            +
                      return status
         | 
| 109 108 | 
             
            	else
         | 
| 110 | 
            -
             | 
| 111 | 
            -
             | 
| 109 | 
            +
                      # Can't compress data
         | 
| 110 | 
            +
                      return status + chan
         | 
| 112 111 | 
             
            	end
         | 
| 113 | 
            -
             | 
| 112 | 
            +
                  end
         | 
| 114 113 |  | 
| 115 | 
            -
             | 
| 114 | 
            +
                  def write_instrument(instrument)
         | 
| 116 115 | 
             
            	event = MetaEvent.new(META_INSTRUMENT, instrument)
         | 
| 117 116 | 
             
            	write_var_len(0)
         | 
| 118 117 | 
             
            	data = event.data_as_bytes()
         | 
| 119 118 | 
             
            	@bytes_written += write_bytes(data)
         | 
| 120 | 
            -
             | 
| 119 | 
            +
                  end
         | 
| 121 120 |  | 
| 122 | 
            -
             | 
| 121 | 
            +
                  def write_var_len(val)
         | 
| 123 122 | 
             
            	buffer = Utils.as_var_len(val)
         | 
| 124 123 | 
             
            	@bytes_written += write_bytes(buffer)
         | 
| 125 | 
            -
             | 
| 124 | 
            +
                  end
         | 
| 126 125 |  | 
| 127 | 
            -
             | 
| 126 | 
            +
                  def write16(val)
         | 
| 128 127 | 
             
            	val = (-val | 0x8000) if val < 0
         | 
| 129 128 |  | 
| 130 129 | 
             
            	buffer = []
         | 
| 131 130 | 
             
            	@io.putc((val >> 8) & 0xff)
         | 
| 132 131 | 
             
            	@io.putc(val & 0xff)
         | 
| 133 132 | 
             
            	@bytes_written += 2
         | 
| 134 | 
            -
             | 
| 133 | 
            +
                  end
         | 
| 135 134 |  | 
| 136 | 
            -
             | 
| 135 | 
            +
                  def write32(val)
         | 
| 137 136 | 
             
            	val = (-val | 0x80000000) if val < 0
         | 
| 138 137 |  | 
| 139 138 | 
             
            	@io.putc((val >> 24) & 0xff)
         | 
| @@ -141,13 +140,13 @@ class SeqWriter | |
| 141 140 | 
             
            	@io.putc((val >> 8) & 0xff)
         | 
| 142 141 | 
             
            	@io.putc(val & 0xff)
         | 
| 143 142 | 
             
            	@bytes_written += 4
         | 
| 144 | 
            -
             | 
| 143 | 
            +
                  end
         | 
| 145 144 |  | 
| 146 | 
            -
             | 
| 145 | 
            +
                  def write_bytes(bytes)
         | 
| 147 146 | 
             
            	bytes.each { |b| @io.putc(b) }
         | 
| 148 147 | 
             
            	bytes.length
         | 
| 148 | 
            +
                  end
         | 
| 149 149 | 
             
                end
         | 
| 150 | 
            -
            end
         | 
| 151 150 |  | 
| 152 | 
            -
            end
         | 
| 151 | 
            +
              end
         | 
| 153 152 | 
             
            end
         |