Music expression as a .ly file.
"""
- ## TODO: support for \relative.
def __init__ (self):
self._line = ''
# 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):
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):
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):
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
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 ''
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.fraction = (4,4)
+ 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):
- return '\\time %d/%d ' % self.fraction
+ 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 st + '\\time %d/%d ' % tuple (self.fractions)
+ elif self.fractions:
+ return st + "\\compoundMeter #'%s" % self.format_fraction (self.fractions)
+ else:
+ return st + ''
class ClefChange (Music):
def __init__ (self):