Relative mode for pitches is now triggered by an -r or --relative
command-line switch.
In this case, each voice is wrapped inside a RelativeMusic wrapper
object, and the previously converted pitch is stored in a global state
variable. The case of chords needs to be handled with special care,
as the whole chord uses the pitch of the first note as its base pitch.
So, after converting all notes in the chord, we have to reset the
global state variable to the pitch of the first note.
Also added myselfs to the copyright output.
from rational import Rational
from rational import Rational
+# Store previously converted pitch for \relative conversion as a global state variable
+previous_pitch = None
+relative_pitches = False
def escape_instrument_string (input_string):
retstring = string.replace (input_string, "\"", "\\\"")
def escape_instrument_string (input_string):
retstring = string.replace (input_string, "\"", "\\\"")
def ly_step_expression (self):
return pitch_generating_function (self)
def ly_step_expression (self):
return pitch_generating_function (self)
-
- def ly_expression (self):
- str = self.ly_step_expression ()
+
+ def absolute_pitch (self):
- str += "'" * (self.octave + 1)
+ return "'" * (self.octave + 1)
- str += "," * (-self.octave - 1)
-
+ return "," * (-self.octave - 1)
+ else:
+ return ''
+
+ def relative_pitch (self):
+ global previous_pitch
+ if not previous_pitch:
+ previous_pitch = self
+ return self.absolute_pitch ()
+ previous_pitch_steps = previous_pitch.octave * 7 + previous_pitch.step
+ this_pitch_steps = self.octave * 7 + self.step
+ pitch_diff = (this_pitch_steps - previous_pitch_steps)
+ previous_pitch = self
+ if pitch_diff > 3:
+ return "'" * ((pitch_diff + 3) / 7)
+ elif pitch_diff < -3:
+ return "," * ((-pitch_diff + 3) / 7)
+ else:
+ return ""
+
+ def ly_expression (self):
+ str = self.ly_step_expression ()
+ if relative_pitches:
+ str += self.relative_pitch ()
+ else:
+ str += self.absolute_pitch ()
+
return str
def print_ly (self, outputter):
return str
def print_ly (self, outputter):
func ('\\%s' % self.mode)
MusicWrapper.print_ly (self, func)
func ('\\%s' % self.mode)
MusicWrapper.print_ly (self, func)
+class RelativeMusic (MusicWrapper):
+ def __init__ (self):
+ MusicWrapper.__init__ (self)
+ self.basepitch = None
+
+ def print_ly (self, func):
+ global previous_pitch
+ global relative_pitches
+ prev_relative_pitches = relative_pitches
+ relative_pitches = True
+ previous_pitch = self.basepitch
+ if not previous_pitch:
+ previous_pitch = Pitch ()
+ func ('\\relative %s%s' % (pitch_generating_function (previous_pitch),
+ previous_pitch.absolute_pitch ()))
+ MusicWrapper.print_ly (self, func)
+ relative_pitches = prev_relative_pitches
+
class TimeScaledMusic (MusicWrapper):
def print_ly (self, func):
func ('\\times %d/%d ' %
class TimeScaledMusic (MusicWrapper):
def print_ly (self, func):
func ('\\times %d/%d ' %
elif len (note_events) == 1:
note_events[0].print_ly (printer)
elif note_events:
elif len (note_events) == 1:
note_events[0].print_ly (printer)
elif note_events:
- pitches = [x.pitch.ly_expression () for x in note_events]
+ global previous_pitch
+ pitches = []
+ basepitch = None
+ for x in note_events:
+ pitches.append (x.pitch.ly_expression ())
+ if not basepitch:
+ basepitch = previous_pitch
printer ('<%s>' % string.join (pitches))
printer ('<%s>' % string.join (pitches))
+ previous_pitch = basepitch
note_events[0].duration.print_ly (printer)
else:
pass
note_events[0].duration.print_ly (printer)
else:
pass
lyrics = {}
return_value = VoiceData ()
return_value.voicedata = voice
lyrics = {}
return_value = VoiceData ()
return_value.voicedata = voice
+
+ # First pitch needed for relative mode (if selected in command-line options)
+ first_pitch = None
# Needed for melismata detection (ignore lyrics on those notes!):
inside_slur = False
# Needed for melismata detection (ignore lyrics on those notes!):
inside_slur = False
voice_builder.add_bar_check (num)
main_event = musicxml_note_to_lily_main_event (n)
voice_builder.add_bar_check (num)
main_event = musicxml_note_to_lily_main_event (n)
+ if main_event and not first_pitch:
+ first_pitch = main_event.pitch
ignore_lyrics = inside_slur or is_tied or is_chord
if hasattr (main_event, 'drum_type') and main_event.drum_type:
ignore_lyrics = inside_slur or is_tied or is_chord
if hasattr (main_event, 'drum_type') and main_event.drum_type:
if len (modes_found) > 1:
error_message ('Too many modes found %s' % modes_found.keys ())
if len (modes_found) > 1:
error_message ('Too many modes found %s' % modes_found.keys ())
+
+ if options.relative:
+ v = musicexp.RelativeMusic ()
+ v.element = seq_music
+ v.basepitch = first_pitch
+ seq_music = v
return_value.ly_voice = seq_music
for mode in modes_found.keys ():
return_value.ly_voice = seq_music
for mode in modes_found.keys ():
- p = ly.get_option_parser(usage=_ ("musicxml2ly FILE.xml"),
+ p = ly.get_option_parser(usage=_ ("musicxml2ly [options] FILE.xml"),
version=('''%prog (LilyPond) @TOPLEVEL_VERSION@\n\n'''
+
_ ("""This program is free software. It is covered by the GNU General Public
version=('''%prog (LilyPond) @TOPLEVEL_VERSION@\n\n'''
+
_ ("""This program is free software. It is covered by the GNU General Public
information.""") % 'lilypond'
+ """
Copyright (c) 2005--2007 by
information.""") % 'lilypond'
+ """
Copyright (c) 2005--2007 by
- Han-Wen Nienhuys <hanwen@xs4all.nl> and
- Jan Nieuwenhuizen <janneke@gnu.org>
+ Han-Wen Nienhuys <hanwen@xs4all.nl>,
+ Jan Nieuwenhuizen <janneke@gnu.org> and
+ Reinhold Kainhofer <reinhold@kainhofer.com>
"""),
description=_ ("Convert %s to LilyPond input.") % 'MusicXML' + "\n")
p.add_option ('-v', '--verbose',
"""),
description=_ ("Convert %s to LilyPond input.") % 'MusicXML' + "\n")
p.add_option ('-v', '--verbose',
default = False,
help = _ ("Input file is a zip-compressed MusicXML file."))
default = False,
help = _ ("Input file is a zip-compressed MusicXML file."))
+ p.add_option ('-r', '--relative',
+ action = "store_true",
+ dest = "relative",
+ help = _ ("Convert pitches in relative mode."))
+
p.add_option ('-l', '--language',
action = "store",
help = _ ("Use a different language file, e.g. 'deutsch' for deutsch.ly."))
p.add_option ('-l', '--language',
action = "store",
help = _ ("Use a different language file, e.g. 'deutsch' for deutsch.ly."))