From 6e1551360eca834933e2bbab5764fb884be2e4dd Mon Sep 17 00:00:00 2001 From: Reinhold Kainhofer Date: Thu, 20 Nov 2008 19:07:05 +0100 Subject: [PATCH] MusicXML: Implement different styles of tuplet brackets and numbers Curved brackets are not yet working... --- .../regression/musicxml/12c-Tuplet-Styles.xml | 218 ++++++++++++------ python/musicexp.py | 40 ++++ scripts/musicxml2ly.py | 53 ++++- 3 files changed, 232 insertions(+), 79 deletions(-) diff --git a/input/regression/musicxml/12c-Tuplet-Styles.xml b/input/regression/musicxml/12c-Tuplet-Styles.xml index d2825d82c9..6b55d4d8ab 100644 --- a/input/regression/musicxml/12c-Tuplet-Styles.xml +++ b/input/regression/musicxml/12c-Tuplet-Styles.xml @@ -24,7 +24,7 @@ major @@ -44,9 +44,8 @@ 3 2 - begin - + @@ -61,7 +60,6 @@ 3 2 - continue @@ -75,7 +73,6 @@ 3 2 - end @@ -92,9 +89,8 @@ 3 2 - begin - + @@ -109,7 +105,6 @@ 3 2 - continue @@ -123,7 +118,6 @@ 3 2 - end @@ -140,9 +134,8 @@ 3 2 - begin - + @@ -157,7 +150,6 @@ 3 2 - continue @@ -171,7 +163,6 @@ 3 2 - end @@ -188,9 +179,53 @@ 3 2 - begin - + + + + + + C + 5 + + 136 + 1 + eighth + + 3 + 2 + + + + + C + 5 + + 136 + 1 + eighth + + 3 + 2 + + + + + + + + C + 5 + + 136 + 1 + eighth + + 3 + 2 + + + @@ -205,7 +240,6 @@ 3 2 - continue @@ -219,7 +253,6 @@ 3 2 - end @@ -239,9 +272,8 @@ 3 2 - begin - + @@ -256,7 +288,6 @@ 3 2 - continue @@ -270,7 +301,6 @@ 3 2 - end @@ -287,9 +317,8 @@ 3 2 - begin - + @@ -304,7 +333,6 @@ 3 2 - continue @@ -318,7 +346,6 @@ 3 2 - end @@ -335,9 +362,8 @@ 3 2 - begin - + @@ -352,7 +378,6 @@ 3 2 - continue @@ -366,7 +391,6 @@ 3 2 - end @@ -383,9 +407,53 @@ 3 2 - begin - + + + + + + C + 5 + + 136 + 1 + eighth + + 3 + 2 + + + + + C + 5 + + 136 + 1 + eighth + + 3 + 2 + + + + + + + + C + 5 + + 136 + 1 + eighth + + 3 + 2 + + + @@ -400,7 +468,6 @@ 3 2 - continue @@ -414,7 +481,6 @@ 3 2 - end @@ -434,9 +500,8 @@ 3 2 - begin - + @@ -451,7 +516,6 @@ 3 2 - continue @@ -465,7 +529,6 @@ 3 2 - end @@ -482,7 +545,6 @@ 3 2 - begin @@ -499,7 +561,6 @@ 3 2 - continue @@ -513,7 +574,6 @@ 3 2 - end @@ -530,9 +590,53 @@ 3 2 - begin - + + + + + + C + 5 + + 136 + 1 + eighth + + 3 + 2 + + + + + C + 5 + + 136 + 1 + eighth + + 3 + 2 + + + + + + + + C + 5 + + 136 + 1 + eighth + + 3 + 2 + + + @@ -547,7 +651,6 @@ 3 2 - continue @@ -561,7 +664,6 @@ 3 2 - end @@ -578,9 +680,8 @@ 3 2 - begin - + @@ -595,7 +696,6 @@ 3 2 - continue @@ -609,7 +709,6 @@ 3 2 - end @@ -634,7 +733,6 @@ 4 3 - begin @@ -651,7 +749,6 @@ 4 3 - continue @@ -665,7 +762,6 @@ 4 3 - continue @@ -679,7 +775,6 @@ 4 3 - end @@ -696,7 +791,6 @@ 17 3 - begin @@ -713,7 +807,6 @@ 17 3 - continue @@ -727,7 +820,6 @@ 17 3 - continue @@ -741,7 +833,6 @@ 17 3 - continue @@ -755,7 +846,6 @@ 17 3 - continue @@ -769,7 +859,6 @@ 17 3 - continue @@ -783,7 +872,6 @@ 17 3 - continue @@ -797,7 +885,6 @@ 17 3 - continue @@ -811,7 +898,6 @@ 17 3 - continue @@ -825,7 +911,6 @@ 17 3 - continue @@ -839,7 +924,6 @@ 17 3 - continue @@ -853,7 +937,6 @@ 17 3 - continue @@ -867,7 +950,6 @@ 17 3 - continue @@ -881,7 +963,6 @@ 17 3 - continue @@ -895,7 +976,6 @@ 17 3 - continue @@ -909,7 +989,6 @@ 17 3 - continue @@ -923,7 +1002,6 @@ 17 3 - end @@ -936,7 +1014,6 @@ 204 1 eighth - begin @@ -946,7 +1023,6 @@ 204 1 eighth - end light-heavy diff --git a/python/musicexp.py b/python/musicexp.py index c0b298f367..bdd7074761 100644 --- a/python/musicexp.py +++ b/python/musicexp.py @@ -452,7 +452,47 @@ class RelativeMusic (MusicWrapper): relative_pitches = prev_relative_pitches class TimeScaledMusic (MusicWrapper): + def __init__ (self): + MusicWrapper.__init__ (self) + self.display_number = "actual" # valid values "actual" | "both" | None + # Display the basic note length for the tuplet: + self.display_type = None # value values "actual" | "both" | None + self.display_bracket = "bracket" # valid values "bracket" | "curved" | None + def print_ly (self, func): + if self.display_bracket == None: + func ("\\once \\override TupletBracket #'stencil = ##f") + func.newline () + elif self.display_bracket == "curved": + warning (_ ("Tuplet brackets of curved shape are not correctly implemented")) + func ("\\once \\override TupletBracket #'stencil = #ly:slur::print") + func.newline () + + base_number_function = {None: "#f", + "actual": "tuplet-number::calc-denominator-text", + "both": "tuplet-number::calc-fraction-text"}.get (self.display_number, None) + + if self.display_type == "actual": + base_duration = "8" # TODO!!! + func ("\\once \\override TupletNumber #'text = #(tuplet-number::append-note-wrapper %s \"%s\")" % + (base_number_function, base_duration)) + func.newline () + elif self.display_type == None: + if self.display_number == None: + func ("\\once \\override TupletNumber #'stencil = ##f") + func.newline () + elif self.display_number == "both": + func ("\\once \\override TupletNumber #'text = #%s" % base_number_function) + func.newline () + elif self.display_type == "both": + warning (_ ("Tuplet brackets displaying both note durations are not implemented, using default")) + if self.display_number == None: + func ("\\once \\override TupletNumber #'stencil = ##f") + func.newline () + elif self.display_number == "both": + func ("\\once \\override TupletNumber #'text = #%s" % base_number_function) + func.newline () + func ('\\times %d/%d ' % (self.numerator, self.denominator)) func.add_factor (Rational (self.numerator, self.denominator)) diff --git a/scripts/musicxml2ly.py b/scripts/musicxml2ly.py index 48ad092feb..b124e99ebe 100644 --- a/scripts/musicxml2ly.py +++ b/scripts/musicxml2ly.py @@ -44,6 +44,7 @@ def error_message (str): needed_additional_definitions = [] additional_definitions = { + "snappizzicato": """#(define-markup-command (snappizzicato layout props) () (interpret-markup layout props (markup #:stencil @@ -54,6 +55,7 @@ additional_definitions = { (list 'draw-line 0.1 0 0.1 0 1) '(-0.1 . 0.1) '(0.1 . 1))) 0.7 X))))""", + "eyeglasses": """eyeglassesps = #"0.15 setlinewidth -0.9 0 translate 1.1 1.1 scale @@ -72,7 +74,20 @@ additional_definitions = { 3.30 2.00 lineto 3.42 2.26 3.80 2.40 3.65 1.70 curveto stroke" -eyeglasses = \markup { \with-dimensions #'(0 . 4.4) #'(0 . 2.5) \postscript #eyeglassesps }""" +eyeglasses = \markup { \with-dimensions #'(0 . 4.4) #'(0 . 2.5) \postscript #eyeglassesps }""", + + "tuplet-note-wrapper": """ % a formatter function, which is simply a wrapper around an existing + % tuplet formatter function. It takes the value returned by the given + % function and appends a note of given length. + #(define-public ((tuplet-number::append-note-wrapper function note) grob) + (let* ((txt (if function (function grob) #f))) + (if txt + (markup txt #:fontsize -5 #:note note UP) + (markup #:fontsize -5 #:note note UP) + ) + ) + )""", + } def round_to_two_digits (val): @@ -592,6 +607,30 @@ def group_repeats (music_list): # TODO: Implement repeats until the end without explicit ending bar return music_list +def musicxml_tuplet_to_lily (tuplet_elt, fraction): + tsm = musicexp.TimeScaledMusic () + tsm.numerator = fraction[0] + tsm.denominator = fraction[1] + + if hasattr (tuplet_elt, 'bracket') and tuplet_elt.bracket == "no": + tsm.display_bracket = None + elif hasattr (tuplet_elt, 'line-shape') and getattr (tuplet_elt, 'line-shape') == "curved": + tsm.display_bracket = "curved" + else: + tsm.display_bracket = "bracket" + + display_values = {"none": None, "actual": "actual", "both": "both"} + if hasattr (tuplet_elt, "show-number"): + tsm.display_number = display_values.get (getattr (tuplet_elt, "show-number"), "actual") + if getattr (tuplet_elt, "show-number") == "both": + needed_additional_definitions.append ("tuplet-note-wrapper") + if hasattr (tuplet_elt, "show-type"): + tsm.display_type = display_values.get (getattr (tuplet_elt, "show-type"), None) + + # TODO: Handle non-standard display (extract the type from the tuplet-actual + # and tuplet-normal children + # TODO: We need the type from the time-modification tag! + return tsm def group_tuplets (music_list, events): @@ -615,18 +654,19 @@ def group_tuplets (music_list, events): if hasattr (tuplet_elt, 'number'): nr = getattr (tuplet_elt, 'number') if tuplet_elt.type == 'start': - tuplet_info = [j, None, fraction] + tuplet_object = musicxml_tuplet_to_lily (tuplet_elt, fraction) + tuplet_info = [j, None, tuplet_object] indices.append (tuplet_info) brackets[nr] = tuplet_info elif tuplet_elt.type == 'stop': bracket_info = brackets.get (nr, None) if bracket_info: - bracket_info[1] = j + bracket_info[1] = j # Set the ending position to j del brackets[nr] new_list = [] last = 0 - for (i1, i2, frac) in indices: + for (i1, i2, tsm) in indices: if i1 > i2: continue @@ -635,12 +675,8 @@ def group_tuplets (music_list, events): last = i2 + 1 seq.elements = music_list[i1:last] - tsm = musicexp.TimeScaledMusic () tsm.element = seq - tsm.numerator = frac[0] - tsm.denominator = frac[1] - new_list.append (tsm) new_list.extend (music_list[last:]) @@ -1999,6 +2035,7 @@ def musicxml_voice_to_lily_voice (voice): for notations in notations_children: for tuplet_event in notations.get_tuplets(): mod = n.get_maybe_exist_typed_child (musicxml.Time_modification) + # TODO: Extract the type of note (for possible display later on!) frac = (1,1) if mod: frac = mod.get_fraction () -- 2.39.5