Mercurial > ~darius > hgwebdir.cgi > musiccutter
changeset 38:9e8ed92b477c
Re-jig note translation to only happen when we are going to emit a
note.
This fixes "note_off with no note_on" cases (iWriteMusic likes to emit
these for rests).
This means some messages have untransposed notes but we draw the line
because they only have to be transposed because of limitations in the
organ so before that they are are untransposed (except for the bulk
adjustment)
author | Daniel O'Connor <darius@dons.net.au> |
---|---|
date | Mon, 23 May 2016 22:35:44 +0930 |
parents | c490fecec0ef |
children | 86622ba474e4 |
files | musiccutter.py |
diffstat | 1 files changed, 34 insertions(+), 29 deletions(-) [+] |
line wrap: on
line diff
--- a/musiccutter.py Mon May 23 21:11:27 2016 +0930 +++ b/musiccutter.py Mon May 23 22:35:44 2016 +0930 @@ -88,38 +88,44 @@ title = os.path.basename(midifile) title, ext = os.path.splitext(title) for ev in midi: - evw = EVWrap(ev) - # Find a slot (plus adjust pitch, attempt transposition etc) - if hasattr(evw.ev, 'note'): - self.getslotfornote(evw, stats, ctime) - # Check if it was unplayable - if not evw.slot: - continue - if evw.ev.type == 'text' and ctime == 0: - title = evw.ev.text + # Adjust pitch + if hasattr(ev, 'note'): + ev.note += self.noteoffset + ctime += ev.time + #print ctime, ev + #Tracer()() - ctime += evw.ev.time - #print ctime, evw.ev - if evw.ev.type == 'note_on' and evw.ev.velocity > 0: - if evw.ev.note in channels[evw.ev.channel]: - print 'Duplicate note_on message %d (%s)' % (evw.ev.note, evw.notename) + if ev.type == 'text' and ctime == 0: + title = ev.text + if ev.type == 'note_on' and ev.velocity > 0: + if ev.note in channels[ev.channel]: + print 'Duplicate note_on message at %.1f sec channel %d note %d' % (ctime, ev.channel, ev.note) + else: + channels[ev.channel][ev.note] = ctime + elif ev.type == 'note_off' or (ev.type == 'note_on' and ev.velocity == 0): + if ev.note not in channels[ev.channel]: + print 'note_off with no corresponding note_on at %.1f sec for channel %d note %d' % (ctime, ev.channel, ev.note) + continue else: - channels[evw.ev.channel][evw.ev.note] = ctime - elif evw.ev.type == 'note_off' or (evw.ev.type == 'note_on' and evw.ev.velocity == 0): - if evw.ev.note not in channels[evw.ev.channel]: - print 'note_off with no corresponding note_on for channel %d note %d' % (evw.ev.channel, evw.ev.note) - else: - start = channels[evw.ev.channel][evw.ev.note] + orignote = ev.note + start = channels[ev.channel][orignote] + evw = EVWrap(ev) + # Find a slot (plus adjust pitch, attempt transposition etc) + if hasattr(ev, 'note'): + self.getslotfornote(evw, stats, ctime) + # Check if it was unplayable + if not evw.slot: + continue notelen = ctime - start - #print 'Note %s (%d) at %.2f length %.2f' % (evw.notename, evw.ev.slot, start, notelen) + #print 'Note %s (%d) at %.2f length %.2f' % (evw.notename, ev.slot, start, notelen) self.emitnote(pdfs, evw.slot, start, notelen * self.notescale) - del channels[evw.ev.channel][evw.ev.note] - elif evw.ev.type == 'end_of_track': + del channels[ev.channel][orignote] + elif ev.type == 'end_of_track': print 'EOT, not flushing, check for missed notes' for chan in channels: - for evw.ev in chan: - print evw.ev + for ev in chan: + print ev print 'Playable count:', stats.playablecount print 'Unplayable count:', stats.unplayablecount @@ -188,8 +194,6 @@ evw.slot = None evw.notename = None - evw.ev.note += self.noteoffset - # First off, is the note in our midi table? if evw.ev.note in self.midi2note: evw.notename = self.midi2note[evw.ev.note] @@ -218,17 +222,18 @@ print 'Note at %.1f sec %d (%s) not playable' % (ctime, evw.ev.note, self.midi2note[evw.ev.note]) stats.unplayablecount += 1 else: - print 'Note at %.1f sec %d not in MIDI table' % (ctime, evw.ev.note) + print 'Note at %.1f sec, %d not in MIDI table' % (ctime, evw.ev.note) stats.unplayablecount += 1 # http://newt.phys.unsw.edu.au/jw/notes.html + # But this seems dumb since the lowest MIDI note is 0 which would be C-1.. @staticmethod def genmidi2note(): '''Create forward & reverse tables for midi number to note name (assuming 69 = A4 = A440)''' names = ['C%d', 'C%d#', 'D%d', 'D%d#', 'E%d', 'F%d', 'F%d#', 'G%d', 'G%d#', 'A%d', 'A%d#', 'B%d'] midi2note = {} note2midi = {} - for midi in range(21, 128): + for midi in range(12, 128): octave = midi / len(names) - 1 index = midi % len(names) name = names[index] % (octave)