This git patch converts dynamic marks and hairpin (de)crescendos from musicxml 
to lilypond.

Unfortunately, I don't have a musicxml editor, so my only test files are the 
output files of several OMR packages (Audiveris and SmartScore). They are way 
too large and to serve as test files...

Cheers,
Reinhold

-- 
------------------------------------------------------------------
Reinhold Kainhofer, Vienna University of Technology, Austria
email: [EMAIL PROTECTED], http://reinhold.kainhofer.com/
 * Financial and Actuarial Mathematics, TU Wien, http://www.fam.tuwien.ac.at/
 * K Desktop Environment, http://www.kde.org, KOrganizer maintainer
 * Chorvereinigung "Jung-Wien", http://www.jung-wien.at/
From f5d10c51caa36baa232a61c8727f29acf6bb472e Mon Sep 17 00:00:00 2001
From: Reinhold Kainhofer <[EMAIL PROTECTED]>
Date: Sat, 18 Aug 2007 12:53:25 +0200
Subject: [PATCH] Convert dynamic marks (given in a <direction> tag, assigned to the staff at a given position in xml, not to a note like in lilypond)

In the LilyPondVoiceBuilder, I added a method to store any pending dynamics and print them out only after the next note or rest (everything with duration>0) is encountered.

Also convert (de-)crescendo (begin/end also given in a <direction> tag, not assigned to a particular note)
---
 python/musicexp.py     |   45 ++++++++++++++++++++++++++++++++++++
 python/musicxml.py     |   10 +++++--
 scripts/musicxml2ly.py |   60 ++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 110 insertions(+), 5 deletions(-)

diff --git a/python/musicexp.py b/python/musicexp.py
index 963b311..4618ea7 100644
--- a/python/musicexp.py
+++ b/python/musicexp.py
@@ -499,6 +499,51 @@ class TieEvent(Event):
         return '~'
 
 
+class HairpinEvent (Event):
+    def __init__ (self, type):
+        self.type = type
+    def hairpin_to_ly (self):
+        val = ''
+        try:
+            val += { 0: '\!', 1: '\<', -1: '\>' }[self.type]
+        except KeyError:
+            pass
+        return val
+    
+    def ly_expression (self):
+        return self.hairpin_to_ly ()
+    
+    def print_ly (self, printer):
+        val = self.hairpin_to_ly ()
+        if val:
+            printer.dump (val)
+
+
+
+class DynamicsEvent (Event):
+    def __init__ (self):
+        self.type = None
+        self.available_commands = [ "ppppp", "pppp", "ppp", "pp", "p", 
+                                    "mp", "mf", 
+                                    "f", "ff", "fff", "ffff", 
+                                    "fp", "sf", "sff", "sp", "spp", "sfz", "rfz" ];
+    def ly_expression (self):
+        if self.type == None:
+            return;
+        elif self.type in self.available_commands:
+            return '\%s' % self.type
+        else:
+            return '\markup{ \dynamic %s }' % self.type
+        
+    def print_ly (self, printer):
+        if self.type == None:
+            return
+        elif self.type in self.available_commands:
+            printer.dump ("\\%s" % self.type)
+        else:
+            printer.dump ("\\markup{ \\dynamic %s }" % self.type)
+
+
 class ArticulationEvent (Event):
     def __init__ (self):
         self.type = None
diff --git a/python/musicxml.py b/python/musicxml.py
index 304b2c6..90d9e45 100644
--- a/python/musicxml.py
+++ b/python/musicxml.py
@@ -354,14 +354,14 @@ class Part (Music_xml_node):
 	for n in elements:
 	    voice_id = n.get_maybe_exist_typed_child (class_dict['voice'])
 
-	    if not (voice_id or isinstance (n, Attributes)):
+	    if not (voice_id or isinstance (n, Attributes) or isinstance (n, Direction) ):
 		continue
 
 	    if isinstance (n, Attributes) and not start_attr:
 		start_attr = n
 		continue
 
-	    if isinstance (n, Attributes):
+	    if isinstance (n, Attributes) or isinstance (n, Direction):
 		for v in voices.values ():
 		    v.add_element (n)
 		continue
@@ -474,6 +474,8 @@ class Direction (Music_xml_node):
     pass
 class DirType (Music_xml_node):
     pass
+class Wedge (Music_xml_node):
+    pass
 
 
 ## need this, not all classes are instantiated
@@ -512,7 +514,9 @@ class_dict = {
         'technical': Technical,
         'ornaments': Ornaments,
         'direction': Direction,
-        'direction-type': DirType
+        'direction-type': DirType,
+        'dynamics': Dynamics,
+        'wedge': Wedge
 }
 
 def name2class_name (name):
diff --git a/scripts/musicxml2ly.py b/scripts/musicxml2ly.py
index bc83031..ed51d9c 100644
--- a/scripts/musicxml2ly.py
+++ b/scripts/musicxml2ly.py
@@ -263,13 +263,46 @@ def musicxml_articulation_to_lily_event(mxl_event):
     return ev
 
 
+def musicxml_direction_to_lily( n ):
+    # TODO: Handle the <staff> element!
+    res = []
+    dirtype = n.get_maybe_exist_typed_child (musicxml.DirType)
+    if not dirtype: 
+      return res
+
+    for entry in dirtype.get_all_children ():
+        if entry.get_name() == "dynamics":
+            for dynentry in entry.get_all_children():
+                dynamics_available = ( "p", "pp", "ppp", "pppp", "ppppp", "pppppp", 
+                    "f", "ff", "fff", "ffff", "fffff", "ffffff", 
+                    "mp", "mf", "sf", "sfp", "sfpp", "fp", 
+                    "rf", "rfz", "sfz", "sffz", "fz" )
+            if not dynentry.get_name() in dynamics_available: 
+                continue
+            event = musicexp.DynamicsEvent ()
+            event.type = dynentry.get_name ()
+            res.append (event)
+      
+        if entry.get_name() == "wedge":
+            try:
+                wedgetype = entry.type;
+                wedgetypeval = None
+                wedgetypeval = {"crescendo" : 1, "decrescendo" : -1, 
+                                "diminuendo" : -1, "stop" : 0 }[wedgetype]
+                if wedgetypeval != None:
+                    event = musicexp.HairpinEvent (wedgetypeval)
+                    res.append (event)
+            except (KeyError, ValueError, AttributeError):
+                continue
+
+    return res
+
 instrument_drumtype_dict = {
     'Acoustic Snare Drum': 'acousticsnare',
     'Side Stick': 'sidestick',
     'Open Triangle': 'opentriangle',
     'Mute Triangle': 'mutetriangle',
-    'Tambourine': 'tambourine',
-    
+    'Tambourine': 'tambourine'
 }
 
 def musicxml_note_to_lily_main_event (n):
@@ -314,6 +347,7 @@ class NegativeSkip:
 class LilyPondVoiceBuilder:
     def __init__ (self):
         self.elements = []
+        self.pending_dynamics = []
         self.end_moment = Rational (0)
         self.begin_moment = Rational (0)
         self.pending_multibar = Rational (0)
@@ -341,6 +375,16 @@ class LilyPondVoiceBuilder:
         self.begin_moment = self.end_moment
         self.end_moment = self.begin_moment + duration 
 
+        # Insert all pending dynamics right after the note/rest:
+        if duration > Rational (0):
+            for d in self.pending_dynamics:
+                self.elements.append (d)
+            self.pending_dynamics = []
+
+    def add_dynamics (self, dynamic):
+        # store the dynamic item(s) until we encounter the next note/rest:
+        self.pending_dynamics.append (dynamic)
+
     def add_bar_check (self, number):
         b = musicexp.BarCheck ()
         b.bar_number = number
@@ -392,6 +436,11 @@ def musicxml_voice_to_lily_voice (voice):
         if n.get_name () == 'forward':
             continue
         
+        if isinstance (n, musicxml.Direction):
+            for a in musicxml_direction_to_lily (n):
+                voice_builder.add_dynamics (a)
+            continue
+        
         if not n.get_maybe_exist_named_child ('chord'):
             try:
                 voice_builder.jumpto (n._when)
@@ -523,6 +572,13 @@ def musicxml_voice_to_lily_voice (voice):
                     if ev: 
                         ev_chord.append (ev)
 
+            dynamics = notations.get_named_children ('dynamics')
+            for a in dynamics:
+                for ch in a.get_all_children ():
+                    ev = musicxml_dynamics_to_lily_event (ch)
+                    if ev:
+                        ev_chord.append (ev)
+
         mxl_beams = [b for b in n.get_named_children ('beam')
                      if (b.get_type () in ('begin', 'end')
                          and b.is_primary ())] 
-- 
1.5.2.3

_______________________________________________
lilypond-devel mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/lilypond-devel

Reply via email to