X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=scripts%2Fmusicxml2ly.py;h=06e7cb7542a5b9482e495a4d20016b4a0855f77e;hb=0e5d83a9ceb4a143f83d22406d7eb816314ff9f7;hp=78d8325c6d5da274871c0d8f30942a93693237ca;hpb=ffd4b1434da640477729308ca47c121d12f008e5;p=lilypond.git diff --git a/scripts/musicxml2ly.py b/scripts/musicxml2ly.py index 78d8325c6d..06e7cb7542 100644 --- a/scripts/musicxml2ly.py +++ b/scripts/musicxml2ly.py @@ -99,8 +99,108 @@ eyeglasses = \markup { \with-dimensions #'(0 . 4.4) #'(0 . 2.5) \postscript #ey (den (if denominator denominator (ly:event-property ev 'denominator))) (num (if numerator numerator (ly:event-property ev 'numerator)))) (format "~a:~a" den num))) -""" +""", + "compound-time-signature": """%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Formatting of (possibly complex) compound time signatures +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +#(define-public (insert-markups l m) + (let* ((ll (reverse l))) + (let join-markups ((markups (list (car ll))) + (remaining (cdr ll))) + (if (pair? remaining) + (join-markups (cons (car remaining) (cons m markups)) (cdr remaining)) + markups)))) + +% Use a centered-column inside a left-column, because the centered column +% moves its reference point to the center, which the left-column undoes. +% The center-column also aligns its contented centered, which is not undone... +#(define-public (format-time-fraction time-sig-fraction) + (let* ((revargs (reverse (map number->string time-sig-fraction))) + (den (car revargs)) + (nums (reverse (cdr revargs)))) + (make-override-markup '(baseline-skip . 0) + (make-number-markup + (make-left-column-markup (list + (make-center-column-markup (list + (make-line-markup (insert-markups nums "+")) + den)))))))) + +#(define-public (format-complex-compound-time time-sig) + (let* ((sigs (map format-time-fraction time-sig))) + (make-override-markup '(baseline-skip . 0) + (make-number-markup + (make-line-markup + (insert-markups sigs (make-vcenter-markup "+"))))))) + +#(define-public (format-compound-time time-sig) + (cond + ((not (pair? time-sig)) (null-markup)) + ((pair? (car time-sig)) (format-complex-compound-time time-sig)) + (else (format-time-fraction time-sig)))) + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Measure length calculation of (possibly complex) compound time signatures +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +#(define-public (calculate-time-fraction time-sig-fraction) + (let* ((revargs (reverse time-sig-fraction)) + (den (car revargs)) + (nums (cdr revargs))) + (ly:make-moment (apply + nums) den))) + +#(define-public (calculate-complex-compound-time time-sig) + (let* ((sigs (map calculate-time-fraction time-sig))) + (let add-moment ((moment ZERO-MOMENT) + (remaining sigs)) + (if (pair? remaining) + (add-moment (ly:moment-add moment (car remaining)) (cdr remaining)) + moment)))) + +#(define-public (calculate-compound-measure-length time-sig) + (cond + ((not (pair? time-sig)) (ly:make-moment 4 4)) + ((pair? (car time-sig)) (calculate-complex-compound-time time-sig)) + (else (calculate-time-fraction time-sig)))) + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Base beat lenth +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +#(define-public (calculate-compound-base-beat-full time-sig) + (let* ((den (map last time-sig))) + (apply max den))) + +#(define-public (calculate-compound-base-beat time-sig) + (ly:make-moment 1 (cond + ((not (pair? time-sig)) 4) + ((pair? (car time-sig)) (calculate-compound-base-beat-full time-sig)) + (else (calculate-compound-base-beat-full (list time-sig)))))) + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% The music function to set the complex time signature +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +compoundMeter = +#(define-music-function (parser location args) (pair?) + (let ((mlen (calculate-compound-measure-length args)) + (beat (calculate-compound-base-beat args))) + #{ +\once \override Staff.TimeSignature #'stencil = #ly:text-interface::print +\once \override Staff.TimeSignature #'text = #(format-compound-time $args) +% \set Staff.beatGrouping = #(reverse (cdr (reverse $args))) +\set Timing.measureLength = $mlen +\set Timing.timeSignatureFraction = #(cons (ly:moment-main-numerator $mlen) + (ly:moment-main-denominator $mlen)) +\set Timing.beatLength = $beat + +% TODO: Implement beatGrouping and auto-beam-settings!!! +#} )) +""" } def round_to_two_digits (val): @@ -726,6 +826,7 @@ def group_tuplets (music_list, events): tsm.element = seq new_list.append (tsm) + #TODO: Handle nested tuplets!!!! new_list.extend (music_list[last:]) return new_list @@ -738,50 +839,75 @@ def musicxml_clef_to_lily (attributes): def musicxml_time_to_lily (attributes): sig = attributes.get_time_signature () - - # TODO: Handle single-digit time sigs - # TODO: Handle senza-misura measures - + if not sig: + return None change = musicexp.TimeSignatureChange() change.fractions = sig + if (len(sig) != 2) or isinstance (sig[0], list): + needed_additional_definitions.append ("compound-time-signature") + + time_elm = attributes.get_maybe_exist_named_child ('time') + if time_elm and hasattr (time_elm, 'symbol'): + change.style = { 'single-number': "'single-digit", + 'cut': None, + 'common': None, + 'normal': "'()"}.get (time_elm.symbol, "'()") + else: + change.style = "'()" + + # TODO: Handle senza-misura measures + # TODO: Handle hidden time signatures (print-object="no") + # TODO: What shall we do if the symbol clashes with the sig? e.g. "cut" + # with 3/8 or "single-number" with (2+3)/8 or 3/8+2/4? return change def musicxml_key_to_lily (attributes): - start_pitch = musicexp.Pitch () - (fifths, mode) = attributes.get_key_signature () - try: - (n,a) = { - 'major' : (0,0), - 'minor' : (5,0), - 'ionian' : (0,0), - 'dorian' : (1,0), - 'phrygian' : (2,0), - 'lydian' : (3,0), - 'mixolydian': (4,0), - 'aeolian' : (5,0), - 'locrian' : (6,0), - }[mode] - start_pitch.step = n - start_pitch.alteration = a - except KeyError: - error_message (_ ("unknown mode %s, expecting 'major' or 'minor'") % mode) - - fifth = musicexp.Pitch() - fifth.step = 4 - if fifths < 0: - fifths *= -1 - fifth.step *= -1 - fifth.normalize () + key_sig = attributes.get_key_signature () + if not key_sig or not (isinstance (key_sig, list) or isinstance (key_sig, tuple)): + error_message (_ ("Unable to extract key signature!")) + return None + + change = musicexp.KeySignatureChange() - for x in range (fifths): - start_pitch = start_pitch.transposed (fifth) + if len (key_sig) == 2 and not isinstance (key_sig[0], list): + # standard key signature, (fifths, mode) + (fifths, mode) = key_sig + change.mode = mode - start_pitch.octave = 0 + start_pitch = musicexp.Pitch () + start_pitch.octave = 0 + try: + (n,a) = { + 'major' : (0,0), + 'minor' : (5,0), + 'ionian' : (0,0), + 'dorian' : (1,0), + 'phrygian' : (2,0), + 'lydian' : (3,0), + 'mixolydian': (4,0), + 'aeolian' : (5,0), + 'locrian' : (6,0), + }[mode] + start_pitch.step = n + start_pitch.alteration = a + except KeyError: + error_message (_ ("unknown mode %s, expecting 'major' or 'minor' " + "or a church mode!") % mode) + + fifth = musicexp.Pitch() + fifth.step = 4 + if fifths < 0: + fifths *= -1 + fifth.step *= -1 + fifth.normalize () + for x in range (fifths): + start_pitch = start_pitch.transposed (fifth) + change.tonic = start_pitch - change = musicexp.KeySignatureChange() - change.mode = mode - change.tonic = start_pitch + else: + # Non-standard key signature of the form [[step,alter<,octave>],...] + change.non_standard_alterations = key_sig return change def musicxml_transpose_to_lily (attributes): @@ -828,7 +954,9 @@ def musicxml_attributes_to_lily (attrs): for (k, func) in attr_dispatch.items (): children = attrs.get_named_children (k) if children: - elts.append (func (attrs)) + ev = func (attrs) + if ev: + elts.append (ev) return elts @@ -1738,6 +1866,7 @@ def musicxml_note_to_lily_main_event (n): def musicxml_lyrics_to_text (lyrics): # TODO: Implement text styles for lyrics syllables continued = False + extended = False text = '' for e in lyrics.get_all_children (): if isinstance (e, musicxml.Syllabic): @@ -1750,15 +1879,24 @@ def musicxml_lyrics_to_text (lyrics): if text: text += " " continued = False + extended = False + elif isinstance (e, musicxml.Extend): + if text: + text += " " + extended = True if text == "-" and continued: return "--" - elif text == "_" and continued: + elif text == "_" and extended: return "__" elif continued and text: return musicxml.escape_ly_output_string (text) + " --" elif continued: return "--" + elif extended and text: + return musicxml.escape_ly_output_string (text) + " __" + elif extended: + return "__" elif text: return musicxml.escape_ly_output_string (text) else: @@ -1930,11 +2068,10 @@ def musicxml_step_to_lily (step): return None def measure_length_from_attributes (attr, current_measure_length): - mxl = attr.get_named_attribute ('time') - if mxl: - return attr.get_measure_length () - else: - return current_measure_length + len = attr.get_measure_length () + if not len: + len = current_measure_length + return len def musicxml_voice_to_lily_voice (voice): tuplet_events = [] @@ -2436,7 +2573,7 @@ If the given filename is -, musicxml2ly reads from the command line. p.version = ('''%prog (LilyPond) @TOPLEVEL_VERSION@\n\n''' + -_ ("""Copyright (c) 2005--2008 by +_ ("""Copyright (c) 2005--2009 by Han-Wen Nienhuys , Jan Nieuwenhuizen and Reinhold Kainhofer @@ -2505,9 +2642,10 @@ information.""") % 'lilypond') dest = 'output_name', help = _ ("set output filename to FILE, stdout if -")) p.add_option_group ('', - description = (_ ("Report bugs via") - + ''' http://post.gmane.org/post.php''' - '''?group=gmane.comp.gnu.lilypond.bugs\n''')) + description = ( + _ ("Report bugs via %s") + % 'http://post.gmane.org/post.php' + '?group=gmane.comp.gnu.lilypond.bugs') + '\n') return p def music_xml_voice_name_to_lily_name (part_id, name):