-) correctly parse compound time signatures and senza-misura signatures.
as a side-effect, crashes on these signatures have been fixed, too.
-) correctly create the time signature change event
-) switch measure length from (num, den) to a Rational
-) Add test cases for general compound time signatures
--- /dev/null
+@section Time signatures
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 1.1 Partwise//EN"
+ "http://www.musicxml.org/dtds/partwise.dtd">
+<score-partwise version="1.1">
+ <identification>
+ <miscellaneous>
+ <miscellaneous-field name="description">Compound time signatures with
+ same denominator: (3+2)/8 and (5+3+1)/4.</miscellaneous-field>
+ </miscellaneous>
+ </identification>
+ <part-list>
+ <score-part id="P1">
+ <part-name>MusicXML Part</part-name>
+ </score-part>
+ </part-list>
+ <!--=========================================================-->
+ <part id="P1">
+ <measure number="1">
+ <attributes>
+ <divisions>2</divisions>
+ <key>
+ <fifths>0</fifths>
+ <mode>major</mode>
+ </key>
+ <time>
+ <beats>3+2</beats>
+ <beat-type>8</beat-type>
+ </time>
+ <clef>
+ <sign>G</sign>
+ <line>2</line>
+ </clef>
+ </attributes>
+ <note>
+ <pitch>
+ <step>B</step>
+ <octave>4</octave>
+ </pitch>
+ <duration>1</duration>
+ <voice>1</voice>
+ <type>eighth</type>
+ <beam number="1">begin</beam>
+ </note>
+ <note>
+ <pitch>
+ <step>B</step>
+ <octave>4</octave>
+ </pitch>
+ <duration>1</duration>
+ <voice>1</voice>
+ <type>eighth</type>
+ <beam number="1">continue</beam>
+ </note>
+ <note>
+ <pitch>
+ <step>B</step>
+ <octave>4</octave>
+ </pitch>
+ <duration>1</duration>
+ <voice>1</voice>
+ <type>eighth</type>
+ <beam number="1">end</beam>
+ </note>
+ <note>
+ <pitch>
+ <step>B</step>
+ <octave>4</octave>
+ </pitch>
+ <duration>1</duration>
+ <voice>1</voice>
+ <type>eighth</type>
+ <beam number="1">begin</beam>
+ </note>
+ <note>
+ <pitch>
+ <step>B</step>
+ <octave>4</octave>
+ </pitch>
+ <duration>1</duration>
+ <voice>1</voice>
+ <type>eighth</type>
+ <beam number="1">end</beam>
+ </note>
+ </measure>
+ <!--=======================================================-->
+ <measure number="2">
+ <attributes>
+ <time>
+ <beats>5+3+1</beats>
+ <beat-type>4</beat-type>
+ </time>
+ </attributes>
+ <note>
+ <pitch>
+ <step>A</step>
+ <octave>4</octave>
+ </pitch>
+ <duration>8</duration>
+ <tie/>
+ <voice>1</voice>
+ <type>whole</type>
+ </note>
+ <note>
+ <pitch>
+ <step>A</step>
+ <octave>4</octave>
+ </pitch>
+ <duration>2</duration>
+ <voice>1</voice>
+ <type>quarter</type>
+ </note>
+ <note>
+ <pitch>
+ <step>A</step>
+ <octave>4</octave>
+ </pitch>
+ <duration>6</duration>
+ <voice>1</voice>
+ <type>half</type>
+ <dot/>
+ </note>
+ <note>
+ <pitch>
+ <step>A</step>
+ <octave>4</octave>
+ </pitch>
+ <duration>2</duration>
+ <voice>1</voice>
+ <type>quarter</type>
+ </note>
+ <barline location="right">
+ <bar-style>light-heavy</bar-style>
+ </barline>
+ </measure>
+ </part>
+ <!--=========================================================-->
+</score-partwise>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 1.1 Partwise//EN"\r
+ "http://www.musicxml.org/dtds/partwise.dtd">\r
+<score-partwise version="1.1">\r
+ <identification>\r
+ <miscellaneous>\r
+ <miscellaneous-field name="description">Compound time signatures with \r
+ separate fractions displayed: 3/8+2/8+3/4 and 5/2+1/8.</miscellaneous-field>\r
+ </miscellaneous>\r
+ </identification>\r
+ <part-list>\r
+ <score-part id="P1">\r
+ <part-name>MusicXML Part</part-name>\r
+ </score-part>\r
+ </part-list>\r
+ <!--=========================================================-->\r
+ <part id="P1">\r
+ <measure number="1">\r
+ <attributes>\r
+ <divisions>2</divisions>\r
+ <key>\r
+ <fifths>0</fifths>\r
+ <mode>major</mode>\r
+ </key>\r
+ <time>\r
+ <beats>3</beats>\r
+ <beat-type>8</beat-type>\r
+ <beats>2</beats>\r
+ <beat-type>8</beat-type>\r
+ <beats>3</beats>\r
+ <beat-type>4</beat-type>\r
+ </time>\r
+ <clef>\r
+ <sign>G</sign>\r
+ <line>2</line>\r
+ </clef>\r
+ </attributes>\r
+ <note>\r
+ <pitch>\r
+ <step>B</step>\r
+ <octave>4</octave>\r
+ </pitch>\r
+ <duration>1</duration>\r
+ <voice>1</voice>\r
+ <type>eighth</type>\r
+ <beam number="1">begin</beam>\r
+ </note>\r
+ <note>\r
+ <pitch>\r
+ <step>B</step>\r
+ <octave>4</octave>\r
+ </pitch>\r
+ <duration>1</duration>\r
+ <voice>1</voice>\r
+ <type>eighth</type>\r
+ <beam number="1">continue</beam>\r
+ </note>\r
+ <note>\r
+ <pitch>\r
+ <step>B</step>\r
+ <octave>4</octave>\r
+ </pitch>\r
+ <duration>1</duration>\r
+ <voice>1</voice>\r
+ <type>eighth</type>\r
+ <beam number="1">end</beam>\r
+ </note>\r
+ <note>\r
+ <pitch>\r
+ <step>B</step>\r
+ <octave>4</octave>\r
+ </pitch>\r
+ <duration>1</duration>\r
+ <voice>1</voice>\r
+ <type>eighth</type>\r
+ <beam number="1">begin</beam>\r
+ </note>\r
+ <note>\r
+ <pitch>\r
+ <step>B</step>\r
+ <octave>4</octave>\r
+ </pitch>\r
+ <duration>1</duration>\r
+ <voice>1</voice>\r
+ <type>eighth</type>\r
+ <beam number="1">end</beam>\r
+ </note>\r
+ <note>\r
+ <pitch>\r
+ <step>B</step>\r
+ <octave>4</octave>\r
+ </pitch>\r
+ <duration>2</duration>\r
+ <voice>1</voice>\r
+ <type>quarter</type>\r
+ </note>\r
+ <note>\r
+ <pitch>\r
+ <step>B</step>\r
+ <octave>4</octave>\r
+ </pitch>\r
+ <duration>2</duration>\r
+ <voice>1</voice>\r
+ <type>quarter</type>\r
+ </note>\r
+ <note>\r
+ <pitch>\r
+ <step>B</step>\r
+ <octave>4</octave>\r
+ </pitch>\r
+ <duration>2</duration>\r
+ <voice>1</voice>\r
+ <type>quarter</type>\r
+ </note>\r
+ </measure>\r
+ <!--=======================================================-->\r
+ <measure number="2">\r
+ <attributes>\r
+ <time>\r
+ <beats>5</beats>\r
+ <beat-type>2</beat-type>\r
+ <beats>1</beats>\r
+ <beat-type>8</beat-type>\r
+ </time>\r
+ </attributes>\r
+ <note>\r
+ <pitch>\r
+ <step>A</step>\r
+ <octave>4</octave>\r
+ </pitch>\r
+ <duration>16</duration>\r
+ <voice>1</voice>\r
+ <type>breve</type>\r
+ </note>\r
+ <note>\r
+ <pitch>\r
+ <step>A</step>\r
+ <octave>4</octave>\r
+ </pitch>\r
+ <duration>4</duration>\r
+ <voice>1</voice>\r
+ <type>half</type>\r
+ </note>\r
+ <note>\r
+ <pitch>\r
+ <step>A</step>\r
+ <octave>4</octave>\r
+ </pitch>\r
+ <duration>1</duration>\r
+ <voice>1</voice>\r
+ <type>eighth</type>\r
+ </note>\r
+ <barline location="right">\r
+ <bar-style>light-heavy</bar-style>\r
+ </barline>\r
+ </measure>\r
+ </part>\r
+ <!--=========================================================-->\r
+</score-partwise>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 1.1 Partwise//EN"\r
+ "http://www.musicxml.org/dtds/partwise.dtd">\r
+<score-partwise version="1.1">\r
+ <identification>\r
+ <miscellaneous>\r
+ <miscellaneous-field name="description">Compound time signatures of\r
+ mixed type: (3+2)/8+3/4.</miscellaneous-field>\r
+ </miscellaneous>\r
+ </identification>\r
+ <part-list>\r
+ <score-part id="P1">\r
+ <part-name>MusicXML Part</part-name>\r
+ </score-part>\r
+ </part-list>\r
+ <!--=========================================================-->\r
+ <part id="P1">\r
+ <measure number="1">\r
+ <attributes>\r
+ <divisions>2</divisions>\r
+ <key>\r
+ <fifths>0</fifths>\r
+ <mode>major</mode>\r
+ </key>\r
+ <time>\r
+ <beats>3+2</beats>\r
+ <beat-type>8</beat-type>\r
+ <beats>3</beats>\r
+ <beat-type>4</beat-type>\r
+ </time>\r
+ <clef>\r
+ <sign>G</sign>\r
+ <line>2</line>\r
+ </clef>\r
+ </attributes>\r
+ <note>\r
+ <pitch>\r
+ <step>B</step>\r
+ <octave>4</octave>\r
+ </pitch>\r
+ <duration>1</duration>\r
+ <voice>1</voice>\r
+ <type>eighth</type>\r
+ <beam number="1">begin</beam>\r
+ </note>\r
+ <note>\r
+ <pitch>\r
+ <step>B</step>\r
+ <octave>4</octave>\r
+ </pitch>\r
+ <duration>1</duration>\r
+ <voice>1</voice>\r
+ <type>eighth</type>\r
+ <beam number="1">continue</beam>\r
+ </note>\r
+ <note>\r
+ <pitch>\r
+ <step>B</step>\r
+ <octave>4</octave>\r
+ </pitch>\r
+ <duration>1</duration>\r
+ <voice>1</voice>\r
+ <type>eighth</type>\r
+ <beam number="1">end</beam>\r
+ </note>\r
+ <note>\r
+ <pitch>\r
+ <step>B</step>\r
+ <octave>4</octave>\r
+ </pitch>\r
+ <duration>1</duration>\r
+ <voice>1</voice>\r
+ <type>eighth</type>\r
+ <beam number="1">begin</beam>\r
+ </note>\r
+ <note>\r
+ <pitch>\r
+ <step>B</step>\r
+ <octave>4</octave>\r
+ </pitch>\r
+ <duration>1</duration>\r
+ <voice>1</voice>\r
+ <type>eighth</type>\r
+ <beam number="1">end</beam>\r
+ </note>\r
+ <note>\r
+ <pitch>\r
+ <step>B</step>\r
+ <octave>4</octave>\r
+ </pitch>\r
+ <duration>2</duration>\r
+ <voice>1</voice>\r
+ <type>quarter</type>\r
+ </note>\r
+ <note>\r
+ <pitch>\r
+ <step>B</step>\r
+ <octave>4</octave>\r
+ </pitch>\r
+ <duration>2</duration>\r
+ <voice>1</voice>\r
+ <type>quarter</type>\r
+ </note>\r
+ <note>\r
+ <pitch>\r
+ <step>B</step>\r
+ <octave>4</octave>\r
+ </pitch>\r
+ <duration>2</duration>\r
+ <voice>1</voice>\r
+ <type>quarter</type>\r
+ </note>\r
+ <barline location="right">\r
+ <bar-style>light-heavy</bar-style>\r
+ </barline>\r
+ </measure>\r
+ </part>\r
+ <!--=========================================================-->\r
+</score-partwise>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 1.1 Partwise//EN"
+ "http://www.musicxml.org/dtds/partwise.dtd">
+<score-partwise version="1.1">
+ <identification>
+ <miscellaneous>
+ <miscellaneous-field name="description">Time signature displayed as a
+ single number.</miscellaneous-field>
+ </miscellaneous>
+ </identification>
+ <part-list>
+ <score-part id="P1">
+ <part-name>MusicXML Part</part-name>
+ </score-part>
+ </part-list>
+ <!--=========================================================-->
+ <part id="P1">
+ <measure number="1">
+ <attributes>
+ <divisions>2</divisions>
+ <key>
+ <fifths>0</fifths>
+ <mode>major</mode>
+ </key>
+ <time symbol="single-number">
+ <beats>3</beats>
+ <beat-type>8</beat-type>
+ </time>
+ <clef>
+ <sign>G</sign>
+ <line>2</line>
+ </clef>
+ </attributes>
+ <note>
+ <pitch>
+ <step>B</step>
+ <octave>4</octave>
+ </pitch>
+ <duration>1</duration>
+ <voice>1</voice>
+ <type>eighth</type>
+ <beam number="1">begin</beam>
+ </note>
+ <note>
+ <pitch>
+ <step>B</step>
+ <octave>4</octave>
+ </pitch>
+ <duration>1</duration>
+ <voice>1</voice>
+ <type>eighth</type>
+ <beam number="1">continue</beam>
+ </note>
+ <note>
+ <pitch>
+ <step>B</step>
+ <octave>4</octave>
+ </pitch>
+ <duration>1</duration>
+ <voice>1</voice>
+ <type>eighth</type>
+ <beam number="1">end</beam>
+ </note>
+ <barline location="right">
+ <bar-style>light-heavy</bar-style>
+ </barline>
+ </measure>
+ </part>
+ <!--=========================================================-->
+</score-partwise>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 1.1 Partwise//EN"
+ "http://www.musicxml.org/dtds/partwise.dtd">
+<score-partwise version="1.1">
+ <identification>
+ <miscellaneous>
+ <miscellaneous-field name="description">Senza-misura time signature</miscellaneous-field>
+ </miscellaneous>
+ </identification>
+ <part-list>
+ <score-part id="P1">
+ <part-name>MusicXML Part</part-name>
+ </score-part>
+ </part-list>
+ <!--=========================================================-->
+ <part id="P1">
+ <measure number="1">
+ <attributes>
+ <divisions>2</divisions>
+ <key>
+ <fifths>0</fifths>
+ <mode>major</mode>
+ </key>
+ <time>
+ <senza-misura/>
+ </time>
+ <clef>
+ <sign>G</sign>
+ <line>2</line>
+ </clef>
+ </attributes>
+ <note>
+ <pitch>
+ <step>B</step>
+ <octave>4</octave>
+ </pitch>
+ <duration>1</duration>
+ <voice>1</voice>
+ <type>eighth</type>
+ <beam number="1">begin</beam>
+ </note>
+ <note>
+ <pitch>
+ <step>B</step>
+ <octave>4</octave>
+ </pitch>
+ <duration>1</duration>
+ <voice>1</voice>
+ <type>eighth</type>
+ <beam number="1">continue</beam>
+ </note>
+ <note>
+ <pitch>
+ <step>B</step>
+ <octave>4</octave>
+ </pitch>
+ <duration>1</duration>
+ <voice>1</voice>
+ <type>eighth</type>
+ <beam number="1">end</beam>
+ </note>
+ <barline location="right">
+ <bar-style>light-heavy</bar-style>
+ </barline>
+ </measure>
+ </part>
+ <!--=========================================================-->
+</score-partwise>
class TimeSignatureChange (Music):
def __init__ (self):
Music.__init__ (self)
- self.fraction = (4,4)
+ self.fractions = [4,4]
def ly_expression (self):
- return '\\time %d/%d ' % self.fraction
+ # 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)
+ elif self.fractions and not isinstance (self.fractions[0], list):
+ # TODO: Implement non-standard time-signatures
+ return ''
+ else:
+ # TODO: Implement non-standard time-signatures
+ return ''
class ClefChange (Music):
def __init__ (self):
Measure_element.__init__ (self)
self._dict = {}
self._original_tag = None
+ self._time_signature_cache = None
def is_first (self):
cn = self._parent.get_typed_children (self.__class__)
def get_named_attribute (self, name):
return self._dict.get (name)
+
+ def single_time_sig_to_fraction (self, sig):
+ if len (sig) < 2:
+ return 0
+ n = 0
+ for i in sig[0:-1]:
+ n += i
+ return Rational (n, sig[-1])
def get_measure_length (self):
- (n,d) = self.get_time_signature ()
- return Rational (n,d)
+ sig = self.get_time_signature ()
+ if len (sig) == 0:
+ return 0
+ if isinstance (sig[0], list):
+ # Complex compound time signature
+ l = 0
+ for i in sig:
+ l += self.single_time_sig_to_fraction (i)
+ return l
+ else:
+ # Simple (maybe compound) time signature of the form (beat, ..., type)
+ return self.single_time_sig_to_fraction (sig)
+ return 0
def get_time_signature (self):
- "return time sig as a (beat, beat-type) tuple"
+ "Return time sig as a (beat, beat-type) tuple. For compound signatures,"
+ "return either (beat, beat,..., beat-type) or ((beat,..., type), "
+ "(beat,..., type), ...)."
+ if self._time_signature_cache:
+ return self._time_signature_cache
try:
mxl = self.get_named_attribute ('time')
- if mxl:
- beats = mxl.get_maybe_exist_named_child ('beats')
- type = mxl.get_maybe_exist_named_child ('beat-type')
- return (int (beats.get_text ()),
- int (type.get_text ()))
- else:
+ if not mxl:
+ return (4, 4)
+
+ if mxl.get_maybe_exist_named_child ('senza-misura'):
+ # TODO: Handle pieces without a time signature!
+ error (_ ("Senza-misura time signatures are not yet supported!"))
return (4, 4)
+ else:
+ signature = []
+ current_sig = []
+ for i in mxl.get_all_children ():
+ if isinstance (i, Beats):
+ beats = string.split (i.get_text ().strip (), "+")
+ current_sig = [int (j) for j in beats]
+ elif isinstance (i, BeatType):
+ current_sig.append (int (i.get_text ()))
+ signature.append (current_sig)
+ current_sig = []
+ if len (signature) == 1 and isinstance (signature[0], list):
+ 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"))
return (4, 4)
+ #except
# returns clef information in the form ("cleftype", position, octave-shift)
def get_clef_information (self):
class FiguredBass (Music_xml_node):
pass
+class Beats (Music_xml_node):
+ pass
+
+class BeatType (Music_xml_node):
+ pass
+
class BeatUnit (Music_xml_node):
pass
'bar-style': BarStyle,
'bass': Bass,
'beam' : Beam,
+ 'beats': Beats,
+ 'beat-type': BeatType,
'beat-unit': BeatUnit,
'beat-unit-dot': BeatUnitDot,
'bend' : Bend,
return change
def musicxml_time_to_lily (attributes):
- (beats, type) = attributes.get_time_signature ()
+ sig = attributes.get_time_signature ()
+
+ # TODO: Handle single-digit time sigs
+ # TODO: Handle senza-misura measures
change = musicexp.TimeSignatureChange()
- change.fraction = (beats, type)
-
+ change.fractions = sig
+
return change
def musicxml_key_to_lily (attributes):
self.pending_multibar = Rational (0)
self.ignore_skips = False
self.has_relevant_elements = False
- self.measure_length = (4, 4)
+ self.measure_length = Rational (4, 4)
def _insert_multibar (self):
layout_information.set_context_item ('Score', 'skipBars = ##t')
r = musicexp.MultiMeasureRest ()
- lenfrac = Rational (self.measure_length[0], self.measure_length[1])
+ lenfrac = self.measure_length
r.duration = rational_to_lily_duration (lenfrac)
r.duration.factor *= self.pending_multibar / lenfrac
self.elements.append (r)
def measure_length_from_attributes (attr, current_measure_length):
mxl = attr.get_named_attribute ('time')
if mxl:
- return attr.get_time_signature ()
+ return attr.get_measure_length ()
else:
return current_measure_length
voice_builder = LilyPondVoiceBuilder ()
figured_bass_builder = LilyPondVoiceBuilder ()
chordnames_builder = LilyPondVoiceBuilder ()
- current_measure_length = (4, 4)
+ current_measure_length = Rational (4, 4)
voice_builder.set_measure_length (current_measure_length)
for n in voice._elements: