From cc8de42490fe9740641a11706596a3ec3188156b Mon Sep 17 00:00:00 2001 From: Reinhold Kainhofer Date: Fri, 3 Apr 2009 17:59:01 +0200 Subject: [PATCH] MusicXML: Fix measure issues with chord names and figured bass -) Add repeats also chordnames and figured bass -) Barlines don't count as relevant voice elements (to check whether a voice is empty) -) Properly insert bar checks for fb and chords, too -) Test files for pickup measures, incomplete measures (skips added!) -) Test file for two harmony elements at the same time (doesn't work correctly!) --- .../musicxml/46f-IncompleteMeasures.xml | 146 ++++++++++++++++++ ...g-PickupMeasure-Chordnames-FiguredBass.xml | 107 +++++++++++++ .../musicxml/71g-MultipleChordnames.xml | 78 ++++++++++ scripts/musicxml2ly.py | 41 +++-- 4 files changed, 360 insertions(+), 12 deletions(-) create mode 100644 input/regression/musicxml/46f-IncompleteMeasures.xml create mode 100644 input/regression/musicxml/46g-PickupMeasure-Chordnames-FiguredBass.xml create mode 100644 input/regression/musicxml/71g-MultipleChordnames.xml diff --git a/input/regression/musicxml/46f-IncompleteMeasures.xml b/input/regression/musicxml/46f-IncompleteMeasures.xml new file mode 100644 index 0000000000..d16a4638f7 --- /dev/null +++ b/input/regression/musicxml/46f-IncompleteMeasures.xml @@ -0,0 +1,146 @@ + + + + + + Measures can contain less notes + than the time signature says. Here, the first and third measures + contain only two quarters instead of four. + + + + + MusicXML Part + + + + + + + 1 + + + G + 2 + + + + + A + 4 + + 1 + 1 + quarter + + + + A + 4 + + 1 + 1 + quarter + + + + + + A + 4 + + 1 + 1 + quarter + + + + A + 4 + + 1 + 1 + quarter + + + + A + 4 + + 1 + 1 + quarter + + + + A + 4 + + 1 + 1 + quarter + + + + + + A + 4 + + 1 + 1 + quarter + + + + A + 4 + + 1 + 1 + quarter + + + + + + A + 4 + + 1 + 1 + quarter + + + + A + 4 + + 1 + 1 + quarter + + + + A + 4 + + 1 + 1 + quarter + + + + A + 4 + + 1 + 1 + quarter + + + + diff --git a/input/regression/musicxml/46g-PickupMeasure-Chordnames-FiguredBass.xml b/input/regression/musicxml/46g-PickupMeasure-Chordnames-FiguredBass.xml new file mode 100644 index 0000000000..99af4c6844 --- /dev/null +++ b/input/regression/musicxml/46g-PickupMeasure-Chordnames-FiguredBass.xml @@ -0,0 +1,107 @@ + + + + + + Pickup measure with chord names + and figured bass. + + + + + MusicXML Part + + + + + + + 2 + + 0 + major + + + + + + C + + major + + +
3
+ 1 +
+ + + C + 5 + + 1 + 1 + eighth + + + + C + 5 + + 1 + 1 + eighth + +
+ + + + C + + major + + +
3
+ 1 +
+ + + C + 4 + + 2 + 1 + quarter + + + + C + 4 + + 2 + 1 + quarter + + + + C + 4 + + 2 + 1 + quarter + + + + C + 4 + + 2 + 1 + quarter + +
+
+
diff --git a/input/regression/musicxml/71g-MultipleChordnames.xml b/input/regression/musicxml/71g-MultipleChordnames.xml new file mode 100644 index 0000000000..6c42cdb2ca --- /dev/null +++ b/input/regression/musicxml/71g-MultipleChordnames.xml @@ -0,0 +1,78 @@ + + + + + + There can be multiple subsequent + harmony elements, indicating a harmony change during a note + + + + + MusicXML Part + + + + + + + 480 + + 0 + major + + + + G + 2 + + + + + C + + major + + + + F + 1 + + minor-sixth + + + + A + 4 + + 960 + 1 + half + + + + D + + minor-seventh + + + + G + + dominant + + + + G + 4 + + 960 + 1 + half + + + + diff --git a/scripts/musicxml2ly.py b/scripts/musicxml2ly.py index 38bfb1949e..561d4cd5da 100644 --- a/scripts/musicxml2ly.py +++ b/scripts/musicxml2ly.py @@ -1906,12 +1906,12 @@ class LilyPondVoiceBuilder: def current_duration (self): return self.end_moment - self.begin_moment - def add_music (self, music, duration): + def add_music (self, music, duration, relevant = True): assert isinstance (music, musicexp.Music) if self.pending_multibar > Rational (0): self._insert_multibar () - self.has_relevant_elements = True + self.has_relevant_elements = self.has_relevant_elements or relevant self.elements.append (music) self.begin_moment = self.end_moment self.set_duration (duration) @@ -1923,18 +1923,27 @@ class LilyPondVoiceBuilder: self.pending_dynamics = [] # Insert some music command that does not affect the position in the measure - def add_command (self, command): + def add_command (self, command, relevant = True): assert isinstance (command, musicexp.Music) if self.pending_multibar > Rational (0): self._insert_multibar () - self.has_relevant_elements = True + self.has_relevant_elements = self.has_relevant_elements or relevant self.elements.append (command) - def add_barline (self, barline): - # TODO: Implement merging of default barline and custom bar line - self.add_music (barline, Rational (0)) + def add_barline (self, barline, relevant = False): + # Insert only if we don't have a barline already + # TODO: Implement proper merging of default barline and custom bar line + has_relevant = self.has_relevant_elements + if (not (self.elements) or + not (isinstance (self.elements[-1], musicexp.BarLine)) or + (self.pending_multibar > Rational (0))): + self.add_music (barline, Rational (0)) + self.has_relevant_elements = has_relevant or relevant def add_partial (self, command): self.ignore_skips = True + # insert the partial, but restore relevant_elements (partial is not relevant) + relevant = self.has_relevant_elements self.add_command (command) + self.has_relevant_elements = relevant def add_dynamics (self, dynamic): # store the dynamic item(s) until we encounter the next note/rest: @@ -1943,11 +1952,9 @@ class LilyPondVoiceBuilder: def add_bar_check (self, number): # re/store has_relevant_elements, so that a barline alone does not # trigger output for figured bass, chord names - has_relevant = self.has_relevant_elements b = musicexp.BarLine () b.bar_number = number self.add_barline (b) - self.has_relevant_elements = has_relevant def jumpto (self, moment): current_end = self.end_moment + self.pending_multibar @@ -1981,7 +1988,7 @@ class LilyPondVoiceBuilder: evc = musicexp.ChordEvent () evc.elements.append (skip) - self.add_music (evc, diff) + self.add_music (evc, diff, False) if diff > Rational (0) and moment == 0: self.ignore_skips = False @@ -2085,6 +2092,8 @@ def musicxml_voice_to_lily_voice (voice): a = musicxml_partial_to_lily (n.partial) if a: voice_builder.add_partial (a) + figured_bass_builder.add_partial (a) + chordnames_builder.add_partial (a) continue is_chord = n.get_maybe_exist_named_child ('chord') @@ -2092,8 +2101,12 @@ def musicxml_voice_to_lily_voice (voice): if not is_chord and not is_after_grace: try: voice_builder.jumpto (n._when) + figured_bass_builder.jumpto (n._when) + chordnames_builder.jumpto (n._when) except NegativeSkip, neg: voice_builder.correct_negative_skip (n._when) + figured_bass_builder.correct_negative_skip (n._when) + chordnames_builder.correct_negative_skip (n._when) n.message (_ ("Negative skip found: from %s to %s, difference is %s") % (neg.here, neg.dest, neg.dest - neg.here)) if isinstance (n, musicxml.Barline): @@ -2101,8 +2114,12 @@ def musicxml_voice_to_lily_voice (voice): for a in barlines: if isinstance (a, musicexp.BarLine): voice_builder.add_barline (a) + figured_bass_builder.add_barline (a, False) + chordnames_builder.add_barline (a, False) elif isinstance (a, RepeatMarker) or isinstance (a, EndingMarker): voice_builder.add_command (a) + figured_bass_builder.add_barline (a, False) + chordnames_builder.add_barline (a, False) continue # Continue any multimeasure-rests before trying to add bar checks! @@ -2431,7 +2448,7 @@ def musicxml_voice_to_lily_voice (voice): # create \figuremode { figured bass elements } if figured_bass_builder.has_relevant_elements: fbass_music = musicexp.SequentialMusic () - fbass_music.elements = figured_bass_builder.elements + fbass_music.elements = group_repeats (figured_bass_builder.elements) v = musicexp.ModeChangingMusicWrapper() v.mode = 'figuremode' v.element = fbass_music @@ -2440,7 +2457,7 @@ def musicxml_voice_to_lily_voice (voice): # create \chordmode { chords } if chordnames_builder.has_relevant_elements: cname_music = musicexp.SequentialMusic () - cname_music.elements = chordnames_builder.elements + cname_music.elements = group_repeats (chordnames_builder.elements) v = musicexp.ModeChangingMusicWrapper() v.mode = 'chordmode' v.element = cname_music -- 2.39.5