From 2f39251576aedd829b69f60b18d2ed2c2bb2be17 Mon Sep 17 00:00:00 2001 From: fred Date: Wed, 27 Mar 2002 02:03:25 +0000 Subject: [PATCH] lilypond-1.5.15 --- CHANGES | 42 +++++++++ modules/midi.c | 5 +- scripts/midi2ly.py | 214 +++++++++++++++++++++++++++++++++------------ 3 files changed, 205 insertions(+), 56 deletions(-) diff --git a/CHANGES b/CHANGES index 260e05ce78..f2a922ccbd 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,45 @@ +1.5.14.jcn6 +=========== + +* Some more random hacking at midi2ly.py. + +* Slightly better doco for r, s and \skip, with examples. + +* Bugfixes: add-html-footer.py and @MAILADDRESS@. + +* Some website related fixes (thanks Tiggr). + +* Ugly hack in add-html-footer for disabling tutorial and refman links +in sidebar. + +* Guile > 1.4 compilation fixes. + +* Website bugfix: mailto: (thanks David Boersma). + +1.5.14.hwn1 +=========== + +* Rename: Local_key_engraver to Accidental_engraver + +* Add documentation for accidentals grob property. + +* Don't make double accidentals even if two of the same notes are +specified. (Thanks Rune) + +* Search all staff-bars for non-empty barline to determine type. This +fixes span-bars with the lowest staff hara-kiried. (Thanks Rune) + + +1.5.14.rz1 +========== + +* Less buggy beam-split + +* Added subdivideBeams, subdividing beams on beats + +1.5.14 +====== + 1.5.13.hwn2 =========== diff --git a/modules/midi.c b/modules/midi.c index 768e6308e9..1228d1c50f 100644 --- a/modules/midi.c +++ b/modules/midi.c @@ -108,6 +108,7 @@ message_t metaEvents[] = { 0x58, "TIME_SIGNATURE", 0x59, "KEY_SIGNATURE", 0x7F, "SEQUENCER_SPECIFIC_META_EVENT", + 0xFF, "META_EVENT", 0,0 }; @@ -285,7 +286,9 @@ midi_parse_track (unsigned char **track, unsigned char *track_end) #endif debug_print ("%s", "\n"); - assert (!strcmp (*track, "MTrk")); + if (!strcmp (*track, "MTrk")) + return midi_error ("parse_track(): MTrk expected"); + *track += 4; track_len = get_number (track, *track + 4, 4); diff --git a/scripts/midi2ly.py b/scripts/midi2ly.py index 26476d49a2..ec72a6a07a 100644 --- a/scripts/midi2ly.py +++ b/scripts/midi2ly.py @@ -2,51 +2,96 @@ import midi import sys +import string -scale_steps =[0,2,4,5,7,9,11] +LINE_BELL = 60 +scale_steps = [0,2,4,5,7,9,11] -def split_channels (track): +def split_track (track): chs = {} for i in range(16): chs[i] = [] for e in track: - data = list (e[1]) - c = data[0] & 0x0f - e = (e[0], tuple ([data[0] & 0xf0] + data[1:])) - chs[c].append (e) + data = list (e[1]) + if data[0] > 0x7f and data[0] < 0xf0: + c = data[0] & 0x0f + e = (e[0], tuple ([data[0] & 0xf0] + data[1:])) + chs[c].append (e) + else: + chs[0].append (e) for i in range (16): if chs[i] == []: del chs[i] - + whatarewes = [] for v in chs.values (): - ns = notes_on_channel(v) - ns = unthread_notes (ns) - map (dump_thread, ns) - - return chs + ns = notes_on_channel (v) + dinges = unthread_notes (ns) + if len (dinges): + whatarewes.append (dinges) + return whatarewes class Note: - def __init__(self, duration, pitch, velocity): + def __init__ (self, duration, pitch, velocity): self.velocity = velocity self.pitch = pitch self.duration = duration - def duration_compare(a,b): - if a.duration < b.duration : + def duration_compare (a, b): + if a.duration < b.duration: return -1 elif a.duration > b.duration: return 1 else: return 0 - + + def dump (self): + return dump_note (self) + +class Time: + def __init__ (self, t, num, den): + self.duration = t + self.num = num + self.den = den + + def dump (self): + return dump_skip (self.duration) + '\\time %d/%d ' % (self.num, self.den) + +class Key: + key_sharps = ('c', 'g', 'd', 'a', 'e', 'b', 'fis') + key_flats = ('BUG', 'f', 'bes', 'es', 'as', 'des', 'ges') + + def __init__ (self, t, sharps, flats, minor): + self.duration = t + self.flats = flats + self.sharps = sharps + self.minor = minor + + def dump (self): + if self.sharps and self.flats: + s = '\\keysignature %s ' % 'TODO' + elif self.sharps: + s = '\\notes\\key %s \major' % key_sharps[self.sharps] + elif self.flats: + s = '\\notes\\key %s \major' % key_flats[self.flats] + return dump_skip (self.duration) + s + + +class Text: + def __init__ (self, text): + self.text = text + self.duration = 0 + + def dump (self): + return dump_text (self) + def notes_on_channel (channel): pitches = {} - nch= [] + nch = [] for e in channel: t = e[0] @@ -62,7 +107,26 @@ def notes_on_channel (channel): except KeyError: pass + elif e[1][0] == midi.META_EVENT: + if e[1][1] == midi.TIME_SIGNATURE: + (num, den, clocks4, count32) = map (ord, e[1][2]) + nch.append ((t, Time (t, num, den))) + elif e[1][1] == midi.KEY_SIGNATURE: + (accidentals, minor) = map (ord, e[1][2]) + sharps = 0 + flats = 0 + if accidentals < 127: + sharps = accidentals + else: + flats = 256 - accidentals + nch.append ((t, Key (t, sharps, flats, minor))) + elif e[1][1] == midi.TEXT_EVENT: + nch.append ((t, Text (e[1][2]))) + else: + sys.stderr.write ("SKIP: %s\n" % `e`) + pass else: + sys.stderr.write ("SKIP: %s\n" % `e`) pass return nch @@ -76,13 +140,15 @@ def unthread_notes (channel): todo = [] for e in channel: t = e[0] - if (t == start_busy_t and e[1].duration + t == end_busy_t) \ - or t >= end_busy_t: + if e[1].__class__ == Note and ((t == start_busy_t and e[1].duration + t == end_busy_t) \ + or t >= end_busy_t): thread.append (e) start_busy_t = t end_busy_t = t + e[1].duration + elif e[1].__class__ == Time or e[1].__class__ == Key or e[1].__class__ == Text: + thread.append (e) else: - todo.append(e) + todo.append (e) threads.append (thread) channel = todo @@ -99,31 +165,21 @@ def gcd (a,b): return a def dump_skip (dt): - wholes = dt / (4*384) - dt = dt % (4*384); - quarters = dt / 384 - - # etc. - if (wholes): - print 's1*%d' % wholes - if quarters: - print 's4*%d' % quarters - - + return 's' + dump_duration (dt) def dump_duration (dur): g = gcd (dur, 384) - sys.stdout.write ('4') + s = '4' (p,q) = (dur / g, 384 / g) if (p == 1 and q == 1) : pass else: if p <> 1: - sys.stdout.write ('*%d'% p) + s = s + '*%d'% p if q <> 1: - sys.stdout.write ('*%d'% q) + s = s + '*%d'% q + return s - def dump_note (note): p = note.pitch oct = p / 12 @@ -136,22 +192,28 @@ def dump_note (note): i = i+1 i = i-1 - str = chr (i + ord ('a')) + str = chr ((i + 2) % 7 + ord ('a')) if scale_steps[i] <> step: str = str + 'is' - sys.stdout.write (' %s' % str); - dump_duration (note.duration) + return ' %s' % str + dump_duration (note.duration) + +def dump (self): + return self.dump () + +def dump_text (text): + return '\n % ' + text.text + '\n ' def dump_chord (ch): + s = '' if len(ch) == 1: - dump_note (ch[0]) + s = dump (ch[0]) else: - sys.stdout.write ("<") - map (dump_note, ch) - sys.stdout.write ('>') + s = '<' + string.join (map (dump, ch)) + '>' + return s -def dump_thread (thread): +# thread? +def dump_channel (thread): last_e = None chs = [] ch = [] @@ -161,46 +223,88 @@ def dump_thread (thread): ch.append (e[1]) else: if ch: - chs.append ( (last_e[0], ch)) + chs.append ((last_e[0], ch)) ch = [e[1]] last_e = e - if ch: chs.append ((last_e[0] ,ch)) + if ch: + chs.append ((last_e[0], ch)) t = 0 last_t = 0 + lines = [''] for ch in chs: + if len (lines[-1]) > LINE_BELL: + lines.append ('') + t = ch[0] if t - last_t: - dump_skip (t-last_t) + lines[-1] = lines[-1] + dump_skip (t-last_t) - dump_chord (ch[1]) + lines[-1] = lines[-1] + dump_chord (ch[1]) + last_t = t + ch[1][0].duration + return string.join (lines, '\n ') + '\n' + def dump_notes (channel): on_hold = [] + s = '' for e in channel: if e[0] <> last_t: - dump_chord (on_hold) + s = s + dump_chord (on_hold) on_hold = [] last_t = e[0] on_hold.append (e) - - - + return s + +def track_name (i): + return 'track%c' % (i + ord ('A')) + +def channel_name (i): + return 'channel%c' % (i + ord ('A')) + +def dump_track (channels, n): + s = '\n' + track = track_name (n) + for i in range (len (channels)): + channel = channel_name (i) + s = s + '%s = \\notes {\n' % (track + channel) + s = s + ' ' + dump_channel (channels[i][0]) + s = s + '}\n\n' + + s = s + '%s = <\n' % track + + for i in range (len (channels)): + channel = channel_name (i) + s = s + ' \\context Voice = %s \\%s\n' % (channel, track + channel) + s = s + '>\n\n' + return s + def convert_midi (f): str = open (f).read () midi_dump = midi.parse (str) - channels = [] - + tracks = [] for t in midi_dump[1]: - channels.append (split_channels (t)) + tracks.append (split_track (t)) + s = '' + for i in range (len (tracks)): + s = s + dump_track (tracks[i], i) + + s = s + '\n\\score {\n <\n' + for i in range (len (tracks)): + track = track_name (i) + s = s + ' \\context Staff=%s \\%s\n' % (track, track) + s = s + ' >\n}\n' + + sys.stdout.write (s) + for f in sys.argv[1:]: - convert_midi (f) + convert_midi (f) -- 2.39.5