midilib icon indicating copy to clipboard operation
midilib copied to clipboard

Keep unusual note off event in input

Open kaorukobo opened this issue 2 years ago • 0 comments

Summary

The proposal to keep the unusual note off event as input. Because the current implementation drops such note-offs and breaks the time of following events.

How to Reproduce Issue

Note: I included the test in this PR.

  1. Copy a sample MIDI file (Auld Lang Syne) with midilib using the following code.
  2. Play both of the original hotaru.mid and the output output.mid. So you'll find the obvious error.
require "midilib"

def read_midifile(infile)
    MIDI::Sequence.new().tap do |seq|
        File.open(infile, 'rb') { |file|
            seq.read(file)
        }
    end
end

def write_midifile(outfile, seq)
    File.open(outfile, 'wb') { |file|
        seq.write(file)
    }
end

# Download a midi file.
system "curl -O 'http://yasashiiorgel.jp/midi/hotaru.mid'"

# Just copy the SMF data as is using midilib.
write_midifile('output.mid', read_midifile('hotaru.mid'))

Detail

The above sample MIDI file has unusual note-off events like this:

[From output of midi-dump https://g200kg.github.io/midi-dump/]

0000a0 00 4f 00                     +0 =      0 :  NoteOn  (ch:1  note:79 velo:0)
0000a3 00 4f 40                     +0 =      0 :  NoteOn  (ch:1  note:79 velo:64)
0000a6 58 3c 00                    +88 =     88 :  NoteOn  (ch:1  note:60 velo:0)
0000a9 00 3c 40                     +0 =     88 :  NoteOn  (ch:1  note:60 velo:64)

Why that? The MIDI is produced by a composer software for DIY hand crank music boxes. To reproduce the instrument's damper behavior, any note-off events always appear just before the corresponding note-on.

As for the above four events, midilib drops the third note-off event because the corresponding note-on event is not found. Therefore the time of the forth note-on event breaks.

kaorukobo avatar Feb 16 '22 02:02 kaorukobo