X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=python%2Fmusicexp.py;h=6bf587be8ff213d184ecac9ca075c87511652de2;hb=22c29f3d7a47390171e830147de3a83065527cab;hp=e69f2ab9f0c9944889c790a514e8bdf9199ff3ee;hpb=ffd4b1434da640477729308ca47c121d12f008e5;p=lilypond.git diff --git a/python/musicexp.py b/python/musicexp.py index e69f2ab9f0..6bf587be8f 100644 --- a/python/musicexp.py +++ b/python/musicexp.py @@ -43,7 +43,6 @@ class Output_printer: Music expression as a .ly file. """ - ## TODO: support for \relative. def __init__ (self): self._line = '' @@ -205,10 +204,20 @@ class Duration: # Implement the different note names for the various languages def pitch_generic (pitch, notenames, accidentals): str = notenames[pitch.step] - if pitch.alteration < 0: - str += accidentals[0] * (-pitch.alteration) + halftones = int (pitch.alteration) + if halftones < 0: + str += accidentals[0] * (-halftones) elif pitch.alteration > 0: - str += accidentals[3] * (pitch.alteration) + str += accidentals[3] * (halftones) + # Handle remaining fraction to pitch.alteration (for microtones) + if (halftones != pitch.alteration): + if None in accidentals[1:3]: + warning (_ ("Language does not support microtones contained in the piece")) + else: + try: + str += {-0.5: accidentals[1], 0.5: accidentals[2]}[pitch.alteration-halftones] + except KeyError: + warning (_ ("Language does not support microtones contained in the piece")) return str def pitch_general (pitch): @@ -230,7 +239,7 @@ def pitch_norsk (pitch): return pitch_deutsch (pitch) def pitch_svenska (pitch): - str = pitch_generic (pitch, ['c', 'd', 'e', 'f', 'g', 'a', 'h'], ['ess', '', '', 'iss']) + str = pitch_generic (pitch, ['c', 'd', 'e', 'f', 'g', 'a', 'h'], ['ess', None, None, 'iss']) return str.replace ('hess', 'b').replace ('aes', 'as').replace ('ees', 'es') def pitch_italiano (pitch): @@ -241,11 +250,11 @@ def pitch_catalan (pitch): return pitch_italiano (pitch) def pitch_espanol (pitch): - str = pitch_generic (pitch, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', '', '', 's']) + str = pitch_generic (pitch, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', None, None, 's']) return str def pitch_vlaams (pitch): - str = pitch_generic (pitch, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', '', '', 'k']) + str = pitch_generic (pitch, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', None, None, 'k']) return str def set_pitch_language (language): @@ -883,10 +892,10 @@ class BarLine (Music): self.type = None def print_ly (self, printer): - bar_symbol = { 'regular': "|", 'dotted': ":", 'dashed': ":", + bar_symbol = { 'regular': "|", 'dotted': ":", 'dashed': "dashed", 'heavy': "|", 'light-light': "||", 'light-heavy': "|.", 'heavy-light': ".|", 'heavy-heavy': ".|.", 'tick': "'", - 'short': "'", 'none': "" }.get (self.type, None) + 'short': "'|", 'none': "" }.get (self.type, None) if bar_symbol <> None: printer.dump ('\\bar "%s"' % bar_symbol) else: @@ -982,7 +991,11 @@ class OctaveShiftEvent (SpanEvent): self.span_type = {'up': 1, 'down': -1}.get (type, 0) def ly_octave_shift_indicator (self): # convert 8/15 to lilypond indicators (+-1/+-2) - value = {8: 1, 15: 2}.get (self.size, 0) + try: + value = {8: 1, 15: 2}[self.size] + except KeyError: + warning (_ ("Invalid octave shift size found: %s. Using no shift.") % self.size) + value = 0 # negative values go up! value *= -1*self.span_type return value @@ -1297,9 +1310,9 @@ class TremoloEvent (ArticulationEvent): class BendEvent (ArticulationEvent): def __init__ (self): Event.__init__ (self) - self.alter = 0 + self.alter = None def ly_expression (self): - if self.alter: + if self.alter != None: return "-\\bendAfter #%s" % self.alter else: return '' @@ -1422,35 +1435,81 @@ class NoteEvent(RhythmicEvent): class KeySignatureChange (Music): def __init__ (self): Music.__init__ (self) - self.scale = [] - self.tonic = Pitch() + self.tonic = None self.mode = 'major' - + self.non_standard_alterations = None + + def format_non_standard_alteration (self, a): + alter_dict = { -2: ",DOUBLE-FLAT", + -1.5: ",THREE-Q-FLAT", + -1: ",FLAT", + -0.5: ",SEMI-FLAT", + 0: ",NATURAL", + 0.5: ",SEMI-SHARP", + 1: ",SHARP", + 1.5: ",THREE-Q-SHARP", + 2: ",DOUBLE-SHARP"} + try: + accidental = alter_dict[a[1]] + except KeyError: + warning (_ ("Unable to convert alteration %s to a lilypond expression") % a[1]) + return '' + if len (a) == 2: + return "( %s . %s )" % (a[0], accidental) + elif len (a) == 3: + return "(( %s . %s ) . %s )" % (a[2], a[0], accidental) + else: + return '' + def ly_expression (self): - return '\\key %s \\%s' % (self.tonic.ly_step_expression (), + if self.tonic: + return '\\key %s \\%s' % (self.tonic.ly_step_expression (), self.mode) - - def lisp_expression (self): - pairs = ['(%d . %d)' % (i , self.scale[i]) for i in range (0,7)] - scale_str = ("'(%s)" % string.join (pairs)) - - return """ (make-music 'KeyChangeEvent - 'pitch-alist %s) """ % scale_str + elif self.non_standard_alterations: + alterations = [self.format_non_standard_alteration (a) for + a in self.non_standard_alterations] + # TODO: Check if the alterations should really be given in reverse + # order of if that's just a bug in Lilypond. If it's a bug, + # fix it and remove the following call, otherwise add a + # proper comment here! + alterations.reverse () + return "\\set Staff.keySignature = #`(%s)" % string.join (alterations, " ") + else: + return '' class TimeSignatureChange (Music): def __init__ (self): Music.__init__ (self) self.fractions = [4,4] + self.style = None + def format_fraction (self, frac): + if isinstance (frac, list): + l = [self.format_fraction (f) for f in frac] + return "(" + string.join (l, " ") + ")" + else: + return "%s" % frac + 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 == "common": + st = "\\defaultTimeSignature" + elif (self.style != "'()"): + st = "\\once \\override Staff.TimeSignature #'style = #%s " % self.style + elif (self.style != "'()") or is_common_signature: + st = "\\numericTimeSignature" + # 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 '' + return st + '\\time %d/%d ' % tuple (self.fractions) + elif self.fractions: + return st + "\\compoundMeter #'%s" % self.format_fraction (self.fractions) else: - # TODO: Implement non-standard time-signatures - return '' + return st + '' class ClefChange (Music): def __init__ (self): @@ -1473,6 +1532,8 @@ class ClefChange (Music): ('F', 4): "bass", ('F', 5): "subbass", ("percussion", 2): "percussion", + # Workaround: MuseScore uses PERC instead of percussion + ("PERC", 2): "percussion", ("TAB", 5): "tab"}.get ((self.type, self.position), None) def ly_expression (self): return '\\clef "%s%s"' % (self.clef_name (), self.octave_modifier ())