lilypond-1.5.15
authorfred <fred>
Wed, 27 Mar 2002 02:03:25 +0000 (02:03 +0000)
committerfred <fred>
Wed, 27 Mar 2002 02:03:25 +0000 (02:03 +0000)
CHANGES
modules/midi.c
scripts/midi2ly.py

diff --git a/CHANGES b/CHANGES
index 260e05ce78e678a885518a6e54cb35efd08c3656..f2a922ccbdda644926a658b727b8f2a98146ba42 100644 (file)
--- 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
 ===========
 
index 768e6308e97e67344a89adf9ab5cfcf9698ccca3..1228d1c50f474b6160822b1a3637384a42095bdc 100644 (file)
@@ -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);
index 26476d49a25ee08533ab08aca0b11e68206cf5d8..ec72a6a07a61c5b1a00f737dd2c8229decc22f42 100644 (file)
@@ -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)