lilypond-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: parallel versus series scoring


From: Nicolas Sceaux
Subject: Re: parallel versus series scoring
Date: Sat, 21 Jan 2006 12:01:39 +0100
User-agent: Gnus/5.11 (Gnus v5.11) Emacs/22.0.50 (darwin)

Han-Wen Nienhuys <address@hidden> writes:

> Nicolas Sceaux wrote:
>> ------------------------------------------------------
>> parallelMusic = #(def-music-function (parser location voice-number
>> music) (number? ly:music?)
>
> it's hack, but it's a cool one. With a little polishing, we should be
> able to put it in the standard distribution. Wouldn't it be better to
> store the voices in different variables? It would be nice to check
> whether the lengths of all bars are equal.

If it were to be actually used, it should be a bit more generic. Maybe:

  \parallelMusic voice-identifiers output-pattern parallel-music

For instance (not workable example, see below):

\parallelMusic #'(voiceA voiceB voiceC)
               << \new Staff \voiceA
                  \new Staff \voiceB
                  \new Staff \voiceC >>
  { c'1 | e' | g' |
    d' | fis' | a' | }

<==>

<< \new Staff { c'1 | d' | }
   \new Staff { e' | fis' | }
   \new Staff { g' | a' | } >>

But the "pattern" argument should not be actually parsed before the
binding to the voice identifiers are created, which is problematic.
Using a string is not really user-friendly, because one would have to
escape all #\\ and #\" characters.

The following example shows a possible implementation (checking bar
length not done yet):

#(use-modules (srfi srfi-1))

#(define (read-bracket-delimited-string chr port)
   "Read a string delimited by #[ #] and return the string."
   (read-char port) ;; discard the first [
   (call-with-output-string
     (lambda (out)
      (do ((c (read-char port) (read-char port)))
          ;; we stop when #] is reached
          ((and (char=? c #\#) (char=? (peek-char port) #\]))
           (read-char port)) ;; discard the last ]
        (display c out)))))

#(read-hash-extend #\[ read-bracket-delimited-string)

parallelMusic = 
#(def-music-function (parser location voice-ids pattern music) (list? string? 
ly:music?)
  (let* ((voices (apply circular-list (make-list (length voice-ids) (list))))
         (current-voices voices))
    (define (push-music m)
      (list-set! current-voices 0 (cons m (car current-voices))))
    (define (change-voice)
      (set! current-voices (cdr current-voices)))
    (define (bar-check? m)
      (eql? (ly:music-property m 'name) 'BarCheck))
    (map-in-order (lambda (m)
                    (push-music m)
                    (if (bar-check? m) (change-voice)))
                  (ly:music-property music 'elements))
    (let ((parser-clone (ly:clone-parser parser)))
      (map (lambda (voice-id voice)
             (ly:parser-define! parser-clone voice-id 
                                (make-music 'SequentialMusic 
                                  'origin location
                                  'elements (reverse! voice))))
           voice-ids voices)
      (ly:parse-string-result pattern parser-clone))))

\parallelMusic #'(voiceA voiceB voiceC)
  ##[
    \new StaffGroup <<
      \new Staff \voiceA
      \new Staff \voiceB
      \new Staff \voiceC
    >> #]
 {
  \time 4/4 
  g' g' g' g' |
  e' e' e' e' |
  c' c' c' c' |
%%
  \time 3/4 a' a' a' | fis' fis' fis' |d' d' d' | 
%%
  \time 2/4 
  b'   b'   c'' c'' |
  gis' gis' a'  a' |
  e'   e'   f'  f' |
}

But then there is still more syntax (#[ #])...

nicolas




reply via email to

[Prev in Thread] Current Thread [Next in Thread]