From 0dba8aca9a2b6a19764622136fd72e8bcc842e19 Mon Sep 17 00:00:00 2001 From: Reinhold Kainhofer Date: Tue, 18 Nov 2008 20:19:21 +0100 Subject: [PATCH 1/1] MusicXML: Implement support for transposed instruments We simply need to take the attribute and determine the correct sounding pitch from the chromatic tag (adjust it enharmonically if an explicit diatonic shift is given)... --- .../musicxml/16-TransposingInstruments.itexi | 2 + .../musicxml/16a-TransposingInstruments.xml | 333 +++++++++++++ .../16b-TransposingInstruments-Full.xml | 453 ++++++++++++++++++ python/musicexp.py | 7 + python/musicxml.py | 5 + scripts/musicxml2ly.py | 36 +- 6 files changed, 835 insertions(+), 1 deletion(-) create mode 100644 input/regression/musicxml/16-TransposingInstruments.itexi create mode 100644 input/regression/musicxml/16a-TransposingInstruments.xml create mode 100644 input/regression/musicxml/16b-TransposingInstruments-Full.xml diff --git a/input/regression/musicxml/16-TransposingInstruments.itexi b/input/regression/musicxml/16-TransposingInstruments.itexi new file mode 100644 index 0000000000..1bdbb55a6e --- /dev/null +++ b/input/regression/musicxml/16-TransposingInstruments.itexi @@ -0,0 +1,2 @@ +@section Transposing instruments + diff --git a/input/regression/musicxml/16a-TransposingInstruments.xml b/input/regression/musicxml/16a-TransposingInstruments.xml new file mode 100644 index 0000000000..82cb627510 --- /dev/null +++ b/input/regression/musicxml/16a-TransposingInstruments.xml @@ -0,0 +1,333 @@ + + + + + + Transposing instruments: Trumpet + in Bb, Horn in Eb, Piano; All of them show the C major scale (the + trumpet with 2 sharp, the horn with 3 sharp). + + + + + Trumpet in Bb + Bb Tpt. + + + Horn in Eb + Hn. + + + Piano + + + + + + + 1 + + 2 + major + + + + G + 2 + + + -1 + -2 + + + + + D + 4 + + 1 + 1 + quarter + + + + E + 4 + + 1 + 1 + quarter + + + + F + 1 + 4 + + 1 + 1 + quarter + + + + G + 4 + + 1 + 1 + quarter + + + + + + + A + 4 + + 1 + 1 + quarter + + + + B + 4 + + 1 + 1 + quarter + + + + C + 1 + 5 + + 1 + 1 + quarter + + + + D + 5 + + 1 + 1 + quarter + + + light-heavy + + + + + + + + 1 + + 3 + major + + + + G + 2 + + + -5 + -9 + + + + + A + 4 + + 1 + 1 + quarter + + + + B + 4 + + 1 + 1 + quarter + + + + C + 1 + 5 + + 1 + 1 + quarter + + + + D + 5 + + 1 + 1 + quarter + + + + + + + E + 5 + + 1 + 1 + quarter + + + + F + 1 + 5 + + 1 + 1 + quarter + + + + G + 1 + 5 + + 1 + 1 + quarter + + + + A + 5 + + 1 + 1 + quarter + + + light-heavy + + + + + + + + 1 + + 0 + major + + + + G + 2 + + + + + C + 4 + + 1 + 1 + quarter + + + + D + 4 + + 1 + 1 + quarter + + + + E + 4 + + 1 + 1 + quarter + + + + F + 4 + + 1 + 1 + quarter + + + + + + + G + 4 + + 1 + 1 + quarter + + + + A + 4 + + 1 + 1 + quarter + + + + B + 4 + + 1 + 1 + quarter + + + + C + 5 + + 1 + 1 + quarter + + + light-heavy + + + + + diff --git a/input/regression/musicxml/16b-TransposingInstruments-Full.xml b/input/regression/musicxml/16b-TransposingInstruments-Full.xml new file mode 100644 index 0000000000..84e1e484fe --- /dev/null +++ b/input/regression/musicxml/16b-TransposingInstruments-Full.xml @@ -0,0 +1,453 @@ + + + + + + Various transposition. Each + part plays a c'', just displayed in different display pitches. + The second-to-last staff uses a transposition where the displayed c' + is an actual f''' concert pitch. The final staff is an untransposed + instrument. + + + + + Clarinet in Eb + Eb Cl. + + + Clarinet in Bb + Bb Cl. + + + Clarinet in A + A Cl. + + + Horn in F + Hn. + + + Horn in Eb + Hn. + + + Piccolo Trumpet in A + Picc.Tpt. + + + Trumpet in Bb + Bb Tpt. + + + Trumpet in C + C Tpt. + + + Trumpet in D + D Tpt. + + + displayed c'=fis''' + + + MusicXML Part + + + + + + + 1 + + 4 + major + + + + G + 2 + + + 2 + 3 + + + + + A + 4 + + 4 + 1 + whole + + + light-heavy + + + + + + + + 1 + + 3 + major + + + + G + 2 + + + -1 + -2 + + + + + D + 5 + + 4 + 1 + whole + + + light-heavy + + + + + + + + 1 + + -2 + major + + + + G + 2 + + + -2 + -3 + + + + + E + -1 + 5 + + 4 + 1 + whole + + + light-heavy + + + + + + + + 1 + + 2 + major + + + + G + 2 + + + -4 + -7 + + + + + G + 5 + + 4 + 1 + whole + + + light-heavy + + + + + + + + 1 + + 4 + major + + + + G + 2 + + + -5 + -9 + + + + + A + 5 + + 4 + 1 + whole + + + light-heavy + + + + + + + + 1 + + -2 + major + + + + G + 2 + + + 5 + 9 + + + + + E + -1 + 4 + + 4 + 1 + whole + + + light-heavy + + + + + + + + 1 + + 3 + major + + + + G + 2 + + + -1 + -2 + + + + + D + 5 + + 4 + 1 + whole + + + light-heavy + + + + + + + + 1 + + 1 + major + + + + G + 2 + + + + + C + 5 + + 4 + 1 + whole + + + light-heavy + + + + + + + + 1 + + -1 + major + + + + G + 2 + + + 1 + 2 + + + + + B + -1 + 4 + + 4 + 1 + whole + + + light-heavy + + + + + + + + 1 + + 7 + major + + + + F + 4 + -1 + + + 3 + 6 + 3 + + + + + F + 1 + 1 + + 4 + 1 + whole + + + light-heavy + + + + + + + + 1 + + 1 + major + + + + G + 2 + + + + + C + 5 + + 4 + 1 + whole + + + light-heavy + + + + + diff --git a/python/musicexp.py b/python/musicexp.py index e0f3f52c97..c0b298f367 100644 --- a/python/musicexp.py +++ b/python/musicexp.py @@ -1355,6 +1355,13 @@ class ClefChange (Music): """ % (glyph, pos, c0) return clefsetting +class Transposition (Music): + def __init__ (self): + Music.__init__ (self) + self.pitch = None + def ly_expression (self): + self.pitch._force_absolute_pitch = True + return '\\transposition %s' % self.pitch.ly_expression () class StaffChange (Music): def __init__ (self, staff): diff --git a/python/musicxml.py b/python/musicxml.py index 498661e621..588a469f97 100644 --- a/python/musicxml.py +++ b/python/musicxml.py @@ -362,6 +362,11 @@ class Attributes (Measure_element): fifths = int (key.get_maybe_exist_named_child ('fifths').get_text ()) return (fifths, mode) + + def get_transposition (self): + return self.get_named_attribute ('transpose') + + class Barline (Measure_element): pass diff --git a/scripts/musicxml2ly.py b/scripts/musicxml2ly.py index a99a5ece80..08f2dc97ba 100644 --- a/scripts/musicxml2ly.py +++ b/scripts/musicxml2ly.py @@ -687,13 +687,47 @@ def musicxml_key_to_lily (attributes): change.mode = mode change.tonic = start_pitch return change + +def musicxml_transpose_to_lily (attributes): + transpose = attributes.get_transposition () + if not transpose: + return None + + shift = musicexp.Pitch () + octave_change = transpose.get_maybe_exist_named_child ('octave-change') + if octave_change: + shift.octave = string.atoi (octave_change.get_text ()) + chromatic_shift = string.atoi (transpose.get_named_child ('chromatic').get_text ()) + chromatic_shift_normalized = chromatic_shift % 12; + (shift.step, shift.alteration) = [ + (0,0), (0,1), (1,0), (2,-1), (2,0), + (3,0), (3,1), (4,0), (5,-1), (5,0), + (6,-1), (6,0)][chromatic_shift_normalized]; + shift.octave += (chromatic_shift - chromatic_shift_normalized) / 12 + + diatonic = transpose.get_maybe_exist_named_child ('diatonic') + if diatonic: + diatonic_step = string.atoi (diatonic.get_text ()) % 7 + if diatonic_step != shift.step: + # We got the alter incorrect! + old_semitones = shift.semitones () + shift.step = diatonic_step + new_semitones = shift.semitones () + shift.alteration += old_semitones - new_semitones + + transposition = musicexp.Transposition () + transposition.pitch = musicexp.Pitch ().transposed (shift) + return transposition + + def musicxml_attributes_to_lily (attrs): elts = [] attr_dispatch = { 'clef': musicxml_clef_to_lily, 'time': musicxml_time_to_lily, - 'key': musicxml_key_to_lily + 'key': musicxml_key_to_lily, + 'transpose': musicxml_transpose_to_lily, } for (k, func) in attr_dispatch.items (): children = attrs.get_named_children (k) -- 2.39.2