]> git.donarmstrong.com Git - lilypond.git/commitdiff
Tremolo cleanup. (issue 3745)
authorDevon Schudy <dschudy@gmail.com>
Sat, 21 Dec 2013 03:55:51 +0000 (22:55 -0500)
committerCarl Sorensen <carl.d.sorensen@gmail.com>
Sun, 12 Jan 2014 02:00:53 +0000 (19:00 -0700)
Scale durations when iterating, not in make-repeat. This means the original
repeat body is intact, so unfold-repeats and display methods no longer need
to undo the scaling.

Build tremolo spanners in Scheme, not C++.

Calculate tremolo-type in tremolo::get-music-list rather than storing it as a property.

shift-duration-log now clears the cached length, since it changes the length.

\shiftDurations no longer duplicates shift-duration-log.

Merge make-repeated-music with make-repeat.

lily/chord-tremolo-iterator.cc
lily/percent-repeat-iterator.cc
ly/music-functions-init.ly
scm/define-music-display-methods.scm
scm/define-music-types.scm
scm/music-functions.scm

index a01c1aa9c1d276ca940b596a8709d8cae2bc7ba3..f73e846bcf01ed1250a8467905305f8b5d34f11c 100644 (file)
@@ -20,9 +20,6 @@
 
 #include "chord-tremolo-iterator.hh"
 
-#include "input.hh"
-#include "international.hh"
-#include "misc.hh"
 #include "repeated-music.hh"
 
 Chord_tremolo_iterator::Chord_tremolo_iterator ()
@@ -33,39 +30,8 @@ SCM
 Chord_tremolo_iterator::get_music_list () const
 {
   Music *mus = get_music ();
-  Input *origin = mus->origin ();
-  Music *body = Repeated_music::body (mus);
-  bool body_is_sequential = body->is_mus_type ("sequential-music");
-
-  int elt_count = body_is_sequential ? scm_ilength (body->get_property ("elements")) : 1;
-
-  if (elt_count <= 0)
-    elt_count = 1;
-
-  if (elt_count == 1)
-    {
-      Music *ev = make_music_by_name (ly_symbol2scm ("TremoloEvent"));
-      ev->set_spot (*origin);
-      ev->set_property ("repeat-count", mus->get_property ("repeat-count"));
-      ev->set_property ("tremolo-type", mus->get_property ("tremolo-type"));
-      return scm_list_2 (ev->unprotect (), body->self_scm ());
-    }
-  else
-    {
-      SCM tremolo_symbol = ly_symbol2scm ("TremoloSpanEvent");
-      SCM start_event_scm = scm_call_2 (ly_lily_module_constant ("make-span-event"), tremolo_symbol, scm_from_int (START));
-      unsmob_music (start_event_scm)->set_spot (*origin);
-      SCM stop_event_scm = scm_call_2 (ly_lily_module_constant ("make-span-event"), tremolo_symbol, scm_from_int (STOP));
-
-      Music *start_event = unsmob_music (start_event_scm);
-      Music *stop_event = unsmob_music (stop_event_scm);
-      start_event->set_spot (*origin);
-      stop_event->set_spot (*origin);
-      start_event->set_property ("repeat-count", mus->get_property ("repeat-count"));
-      start_event->set_property ("tremolo-type", mus->get_property ("tremolo-type"));
-
-      return scm_list_3 (start_event_scm, body->self_scm (), stop_event_scm);
-    }
+  SCM proc = ly_lily_module_constant ("tremolo::get-music-list");
+  return scm_call_1 (proc, mus->self_scm ());
 }
 
 IMPLEMENT_CTOR_CALLBACK (Chord_tremolo_iterator);
index 25aa9bf3eef6293e1e8b3fbff2bb55475010c7e7..c2779f97e33b8b637c4f938a9da453b3e3ddf370 100644 (file)
@@ -43,6 +43,7 @@ SCM
 Percent_repeat_iterator::get_music_list () const
 {
   Music *mus = get_music ();
+
   Music *child = Repeated_music::body (mus);
   SCM length = child->get_length ().smobbed_copy ();
   SCM child_list = SCM_EOL;
index 11dcb53556c3ee229bfd75218b201882bdac687f..0ef5b397e1da1257a84d63694b75c8a550b61562 100644 (file)
@@ -1281,9 +1281,7 @@ shiftDurations =
    (_i "Change the duration of @var{arg} by adding @var{dur} to the
 @code{durlog} of @var{arg} and @var{dots} to the @code{dots} of @var{arg}.")
 
-   (music-map
-    (lambda (x)
-      (shift-one-duration-log x dur dots)) arg))
+   (shift-duration-log arg dur dots))
 
 single =
 #(define-music-function (parser location overrides music)
index 0c4674384d133cb68b783b9659354e90a952fb36..431f9a6e954d31d22a90f185122539acca30a662 100644 (file)
@@ -724,29 +724,7 @@ Otherwise, return #f."
   (repeat->lily-string expr "percent" parser))
 
 (define-display-method TremoloRepeatedMusic (expr parser)
-  (let* ((main (ly:music-property expr 'element))
-         (children (if (music-is-of-type? main 'sequential-music)
-                       ;; \repeat tremolo n { ... }
-                       (length (extract-named-music main '(EventChord
-                                                           NoteEvent)))
-                       ;; \repeat tremolo n c4
-                       1))
-         (times (ly:music-property expr 'repeat-count))
-
-         ;; # of dots is equal to the 1 in bitwise representation (minus 1)!
-         (dots (1- (logcount (* times children))))
-         ;; The remaining missing multiplicator to scale the notes by
-         ;; times * children
-         (mult (/ (* times children (ash 1 dots)) (1- (ash 2 dots))))
-         (shift (- (ly:intlog2 (floor mult)))))
-    (set! main (ly:music-deep-copy main))
-    ;; Adjust the time of the notes
-    (ly:music-compress main (ly:make-moment children 1))
-    ;; Adjust the displayed note durations
-    (shift-duration-log main (- shift) (- dots))
-    (format #f "\\repeat tremolo ~a ~a"
-            times
-            (music->lily-string main parser))))
+  (repeat->lily-string expr "tremolo" parser))
 
 ;;;
 ;;; Contexts
index c71265a3ede0407cf03ce42e024cee7f23b65df1..8d0464bf4c9009f2c86955ea5f9a7d4520ca3582 100644 (file)
@@ -685,8 +685,7 @@ Syntax: @code{\\times @var{fraction} @var{music}}, e.g.,
      . ((description . "Repeated notes denoted by tremolo beams.")
         (iterator-ctor . ,ly:chord-tremolo-iterator::constructor)
         (start-callback .  ,ly:repeated-music::first-start)
-        ;; the length of the repeat is handled by shifting the note logs
-        (length-callback . ,ly:repeated-music::folded-music-length)
+        (length-callback . ,ly:repeated-music::unfolded-music-length)
         (types . (general-music repeated-music tremolo-repeated-music))
         ))
 
@@ -815,16 +814,3 @@ override earlier ones."
                      (ly:error (_ "bad make-music argument: ~S") e))))))
       (set-props music-properties)
       m)))
-
-(define-public (make-repeated-music name)
-  (let* ((repeated-music (assoc-get name '(("volta" . VoltaRepeatedMusic)
-                                           ("unfold" . UnfoldedRepeatedMusic)
-                                           ("percent" . PercentRepeatedMusic)
-                                           ("tremolo" . TremoloRepeatedMusic))))
-         (repeated-music-name (if repeated-music
-                                  repeated-music
-                                  (begin
-                                    (ly:warning (_ "unknown repeat type `~S'") name)
-                                    (ly:warning (_ "See define-music-types.scm for supported repeats"))
-                                    'VoltaRepeatedMusic))))
-    (make-music repeated-music-name)))
index 05352b0953038c23babc807a6746b9a539453038..c7f41eaad8d4962a352f72c35eda7b24e9ecc3ad 100644 (file)
@@ -243,18 +243,23 @@ The number of dots in the shifted music may not be less than zero."
                     (max 0 (+ dot (ly:duration-dot-count d)))
                     cp)))
           (set! (ly:music-property music 'duration) nd)))
+    ;clear cached length, since it's no longer valid
+    (set! (ly:music-property music 'length) '())
     music))
 
 (define-public (shift-duration-log music shift dot)
   (music-map (lambda (x) (shift-one-duration-log x shift dot))
              music))
 
-(define-public (make-repeat name times main alts)
-  "Create a repeat music expression, with all properties initialized
-properly."
+(define-public (tremolo::get-music-list tremolo)
+  "Given a tremolo repeat, return a list of music to engrave for it.
+This will be a stretched copy of its body, plus a TremoloEvent or
+TremoloSpanEvent.
+
+This is called only by Chord_tremolo_iterator."
   (define (first-note-duration music)
-    "Finds the duration of the first NoteEvent by searching depth-first
-through MUSIC."
+    "Finds the duration of the first NoteEvent by searching
+depth-first through MUSIC."
     ;; NoteEvent or a non-expanded chord-repetition
     ;; We just take anything that actually sports an announced duration.
     (if (ly:duration? (ly:music-property music 'duration))
@@ -267,46 +272,72 @@ through MUSIC."
                  (if (ly:duration? dur)
                      dur
                      (loop (cdr elts))))))))
-
-  (let ((talts (if (< times (length alts))
-                   (begin
-                     (ly:warning (_ "More alternatives than repeats.  Junking excess alternatives"))
-                     (take alts times))
-                   alts))
-        (r (make-repeated-music name)))
-    (set! (ly:music-property r 'element) main)
-    (set! (ly:music-property r 'repeat-count) (max times 1))
-    (set! (ly:music-property r 'elements) talts)
-    (if (and (equal? name "tremolo")
-             (pair? (extract-named-music main '(EventChord NoteEvent))))
-        ;; This works for single-note and multi-note tremolos!
-        (let* ((children (if (music-is-of-type? main 'sequential-music)
-                             ;; \repeat tremolo n { ... }
-                             (length (extract-named-music main '(EventChord
-                                                                 NoteEvent)))
-                             ;; \repeat tremolo n c4
-                             1))
-               ;; # of dots is equal to the 1 in bitwise representation (minus 1)!
-               (dots (1- (logcount (* times children))))
-               ;; The remaining missing multiplicator to scale the notes by
+  (let* ((times (ly:music-property tremolo 'repeat-count))
+         (body (ly:music-property tremolo 'element))
+         (children (if (music-is-of-type? body 'sequential-music)
+                       ;; \repeat tremolo n { ... }
+                       (length (extract-named-music body '(EventChord
+                                                           NoteEvent)))
+                       ;; \repeat tremolo n c4
+                       1))
+         (tremolo-type (if (positive? children)
+                           (let* ((note-duration (first-note-duration body))
+                                  (duration-log (if (ly:duration? note-duration)
+                                                    (ly:duration-log note-duration)
+                                                    1)))
+                             (ash 1 duration-log))
+                           '()))
+         (stretched (ly:music-deep-copy body)))
+    (if (positive? children)
+        ;; # of dots is equal to the 1 in bitwise representation (minus 1)!
+        (let* ((dots (1- (logcount (* times children))))
+               ;; The remaining missing multiplier to scale the notes by
                ;; times * children
                (mult (/ (* times children (ash 1 dots)) (1- (ash 2 dots))))
-               (shift (- (ly:intlog2 (floor mult))))
-               (note-duration (first-note-duration r))
-               (duration-log (if (ly:duration? note-duration)
-                                 (ly:duration-log note-duration)
-                                 1))
-               (tremolo-type (ash 1 duration-log)))
-          (set! (ly:music-property r 'tremolo-type) tremolo-type)
+               (shift (- (ly:intlog2 (floor mult)))))
           (if (not (and (integer? mult) (= (logcount mult) 1)))
               (ly:music-warning
-               main
+               body
                (ly:format (_ "invalid tremolo repeat count: ~a") times)))
-          ;; Adjust the time of the notes
-          (ly:music-compress r (ly:make-moment 1 children))
+          ;; Make each note take the full duration
+          (ly:music-compress stretched (ly:make-moment 1 children))
           ;; Adjust the displayed note durations
-          (shift-duration-log r shift dots))
-        r)))
+          (shift-duration-log stretched shift dots)))
+    ;; Return the stretched body plus a tremolo event
+    (if (= children 1)
+        (list (make-music 'TremoloEvent
+                          'repeat-count times
+                          'tremolo-type tremolo-type
+                          'origin (ly:music-property tremolo 'origin))
+              stretched)
+        (list (make-music 'TremoloSpanEvent
+                          'span-direction START
+                          'repeat-count times
+                          'tremolo-type tremolo-type
+                          'origin (ly:music-property tremolo 'origin))
+              stretched
+              (make-music 'TremoloSpanEvent
+                          'span-direction STOP
+                          'origin (ly:music-property tremolo 'origin))))))
+
+(define-public (make-repeat name times main alts)
+  "Create a repeat music expression, with all properties initialized
+properly."
+  (let ((type (or (assoc-get name '(("volta" . VoltaRepeatedMusic)
+                                    ("unfold" . UnfoldedRepeatedMusic)
+                                    ("percent" . PercentRepeatedMusic)
+                                    ("tremolo" . TremoloRepeatedMusic)))
+                  (begin (ly:warning (_ "unknown repeat type `~S': must be volta, unfold, percent, or tremolo") name)
+                         'VoltaRepeatedMusic)))
+        (talts (if (< times (length alts))
+                   (begin
+                     (ly:warning (_ "More alternatives than repeats.  Junking excess alternatives"))
+                     (take alts times))
+                   alts)))
+    (make-music type
+                'element main
+                'repeat-count (max times 1)
+                'elements talts)))
 
 (define (calc-repeat-slash-count music)
   "Given the child-list @var{music} in @code{PercentRepeatMusic},
@@ -341,40 +372,10 @@ beats to be distinguished."
 
 (define-public (unfold-repeats music)
   "Replace all repeats with unfolded repeats."
-
   (let ((es (ly:music-property music 'elements))
         (e (ly:music-property music 'element)))
-
     (if (music-is-of-type? music 'repeated-music)
-        (let* ((props (ly:music-mutable-properties music))
-               (old-name (ly:music-property music 'name))
-               (flattened (flatten-alist props)))
-          (set! music (apply make-music (cons 'UnfoldedRepeatedMusic
-                                              flattened)))
-
-          (if (and (equal? old-name 'TremoloRepeatedMusic)
-                   (pair? (extract-named-music e '(EventChord NoteEvent))))
-              ;; This works for single-note and multi-note tremolos!
-              (let* ((children (if (music-is-of-type? e 'sequential-music)
-                                   ;; \repeat tremolo n { ... }
-                                   (length (extract-named-music e '(EventChord
-                                                                    NoteEvent)))
-                                   ;; \repeat tremolo n c4
-                                   1))
-                     (times (ly:music-property music 'repeat-count))
-
-                     ;; # of dots is equal to the 1 in bitwise representation (minus 1)!
-                     (dots (1- (logcount (* times children))))
-                     ;; The remaining missing multiplicator to scale the notes by
-                     ;; times * children
-                     (mult (/ (* times children (ash 1 dots)) (1- (ash 2 dots))))
-                     (shift (- (ly:intlog2 (floor mult)))))
-
-                ;; Adjust the time of the notes
-                (ly:music-compress music (ly:make-moment children 1))
-                ;; Adjust the displayed note durations
-                (shift-duration-log music (- shift) (- dots))))))
-
+        (set! music (make-music 'UnfoldedRepeatedMusic music)))
     (if (pair? es)
         (set! (ly:music-property music 'elements)
               (map unfold-repeats es)))