#include "chord-tremolo-iterator.hh"
-#include "input.hh"
-#include "international.hh"
-#include "misc.hh"
#include "repeated-music.hh"
Chord_tremolo_iterator::Chord_tremolo_iterator ()
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);
(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))
(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},
(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)))