From 16a8f58411d86538db19153ee6f365e9f469df78 Mon Sep 17 00:00:00 2001 From: Reinhold Kainhofer Date: Sun, 30 Nov 2008 17:46:04 +0100 Subject: [PATCH] MusicXML: Implement the symbol attribute of time signatures -) Fix time keeping (i.e. use the cached value for the current time sig and thus the current measure length!): revert to self.get_named_attribute ('time') -) Implement single-digit time signatures -) Implement C vs. numeric time signatures; Change the signature style to '() only if a C or C/ would be printed (i.e. 2/2 or 4/4). By default, MusicXML uses numeric signatures (style '()), while LilyPond's default is 'C, so we have to add some manual overrides in those cases of 2/2 or 4/4 where no symbol is given in the MusicXML file --- .../11f-TimeSignatures-SymbolMeaning.xml | 108 ++++++++++++++++++ python/musicexp.py | 16 ++- python/musicxml.py | 16 +-- scripts/musicxml2ly.py | 33 ++++-- 4 files changed, 150 insertions(+), 23 deletions(-) create mode 100644 input/regression/musicxml/11f-TimeSignatures-SymbolMeaning.xml diff --git a/input/regression/musicxml/11f-TimeSignatures-SymbolMeaning.xml b/input/regression/musicxml/11f-TimeSignatures-SymbolMeaning.xml new file mode 100644 index 0000000000..4787a71149 --- /dev/null +++ b/input/regression/musicxml/11f-TimeSignatures-SymbolMeaning.xml @@ -0,0 +1,108 @@ + + + + + + A time signature of 3/8 with the + symbol="cut" attribute and two symbol="single-number" attributes with + compound time signatures. Shall the symbol be ignored in this + case? + + + + + MusicXML Part + + + + + + + 2 + + 0 + major + + + + G + 2 + + + + + B + 4 + + 3 + 1 + quarter + + + + + + + + + + + B + 4 + + 1 + 1 + eighth + + + + B + 4 + + 4 + 1 + half + + + + + + + + + + B + 4 + + 1 + 1 + eighth + + + + B + 4 + + 4 + 1 + half + + + light-heavy + + + + + diff --git a/python/musicexp.py b/python/musicexp.py index e69f2ab9f0..c5635a2c02 100644 --- a/python/musicexp.py +++ b/python/musicexp.py @@ -1441,16 +1441,26 @@ class TimeSignatureChange (Music): def __init__ (self): Music.__init__ (self) self.fractions = [4,4] + self.style = None def ly_expression (self): + st = '' + # Print out the style if we have ome, but the '() should only be + # forced for 2/2 or 4/4, since in all other cases we'll get numeric + # signatures anyway despite the default 'C signature style! + is_common_signature = self.fractions in ([2,2], [4,4], [4,2]) + if self.style: + if (self.style != "'()") or is_common_signature: + st = "\\once \\override Staff.TimeSignature #'style = #%s " % self.style + # Easy case: self.fractions = [n,d] => normal \time n/d call: if len (self.fractions) == 2 and isinstance (self.fractions[0], int): - return '\\time %d/%d ' % tuple (self.fractions) + return st + '\\time %d/%d ' % tuple (self.fractions) elif self.fractions and not isinstance (self.fractions[0], list): # TODO: Implement non-standard time-signatures - return '' + return st + '' else: # TODO: Implement non-standard time-signatures - return '' + return st + '' class ClefChange (Music): def __init__ (self): diff --git a/python/musicxml.py b/python/musicxml.py index 1ababbc7d5..115bfaa445 100644 --- a/python/musicxml.py +++ b/python/musicxml.py @@ -323,8 +323,8 @@ class Attributes (Measure_element): def get_measure_length (self): sig = self.get_time_signature () - if len (sig) == 0: - return 0 + if not sig or len (sig) == 0: + return 1 if isinstance (sig[0], list): # Complex compound time signature l = 0 @@ -346,7 +346,7 @@ class Attributes (Measure_element): try: mxl = self.get_named_attribute ('time') if not mxl: - return (4, 4) + return None if mxl.get_maybe_exist_named_child ('senza-misura'): # TODO: Handle pieces without a time signature! @@ -363,17 +363,13 @@ class Attributes (Measure_element): current_sig.append (int (i.get_text ())) signature.append (current_sig) current_sig = [] - if len (signature) == 1 and isinstance (signature[0], list): + if isinstance (signature[0], list) and len (signature) == 1: signature = signature[0] - if len (signature) ==0: - error (_ ("requested time signature, but time sig is unknown")) - return (4, 4) self._time_signature_cache = signature return signature - except KeyError: - error (_ ("requested time signature, but time sig is unknown")) + except (KeyError, ValueError): + self.message (_ ("Unable to interpret time signature! Falling back to 4/4.")) return (4, 4) - #except # returns clef information in the form ("cleftype", position, octave-shift) def get_clef_information (self): diff --git a/scripts/musicxml2ly.py b/scripts/musicxml2ly.py index 78d8325c6d..e06795d69b 100644 --- a/scripts/musicxml2ly.py +++ b/scripts/musicxml2ly.py @@ -738,13 +738,25 @@ def musicxml_clef_to_lily (attributes): def musicxml_time_to_lily (attributes): sig = attributes.get_time_signature () - - # TODO: Handle single-digit time sigs - # TODO: Handle senza-misura measures - + if not sig: + return None change = musicexp.TimeSignatureChange() change.fractions = sig + time_elm = attributes.get_maybe_exist_named_child ('time') + if time_elm and hasattr (time_elm, 'symbol'): + change.style = { 'single-number': "'single-digit", + 'cut': None, + 'common': None, + 'normal': "'()"}.get (time_elm.symbol, "'()") + else: + change.style = "'()" + + # TODO: Handle senza-misura measures + # TODO: Handle hidden time signatures (print-object="no") + # TODO: What shall we do if the symbol clashes with the sig? e.g. "cut" + # with 3/8 or "single-number" with (2+3)/8 or 3/8+2/4? + return change def musicxml_key_to_lily (attributes): @@ -828,7 +840,9 @@ def musicxml_attributes_to_lily (attrs): for (k, func) in attr_dispatch.items (): children = attrs.get_named_children (k) if children: - elts.append (func (attrs)) + ev = func (attrs) + if ev: + elts.append (ev) return elts @@ -1930,11 +1944,10 @@ def musicxml_step_to_lily (step): return None def measure_length_from_attributes (attr, current_measure_length): - mxl = attr.get_named_attribute ('time') - if mxl: - return attr.get_measure_length () - else: - return current_measure_length + len = attr.get_measure_length () + if not len: + len = current_measure_length + return len def musicxml_voice_to_lily_voice (voice): tuplet_events = [] -- 2.39.5