Am Sa., 5. Dez. 2020 um 21:42 Uhr schrieb Petr Pařízek
<[email protected]>:
>
> Thomas Morley wrote:
>
>
>  > Amending the shared code, you could probably do
>
> [snip]
>
> Could you explain what your suggested piece of code actually does --
> i.e. what's the supposed input data and what's the supposed output?
> Thanks.
>
> Petr
>
>
>
> --
> Tento e-mail byl zkontrolován na viry programem AVG.
> http://www.avg.cz
>
>

Not sure I understand your question.
Iiuc, it does what you want:
It takes a music-expression and transforms every found chord with
\arpeggio into simultaneous music (via applying `midiArpeggio`).
As a result you'll hear an arpeggio in midi.

Full example attached.

Cheers,
  Harm
%% by H. S. Teoh
%% https://lists.gnu.org/archive/html/lilypond-user/2020-12/msg00036.html
%
% A scheme function that unpacks a rolled chord into displaced notes with
% adjusted lengths such that it will render nicely in MIDI.
%
\version "2.20.1"

% Returns: A skip followed by the given note, with the skip scaled by n/d of
% the note's length, and the note scaled by (d-n)/d of its original length.
#(define shiftedNote (lambda (num denom note)
    (if (= num 0)
        ; First note is unchanged
        note
        ; Construct a skip + the note, both appropriately scaled
        (let ((dLog (ly:duration-log (ly:music-property note 'duration)))
              (dDot (ly:duration-dot-count (ly:music-property note 'duration)))
              (dFac (ly:duration-factor (ly:music-property note 'duration)))
              (scaledNote (ly:music-deep-copy note)))
            (set! (ly:music-property scaledNote 'duration)
                  (ly:make-duration dLog dDot (*
                    (/ (car dFac) (cdr dFac))
                    (/ (- denom num) denom))))
            (make-music 'SequentialMusic
                'elements (list
                    (make-music 'SkipEvent
                        'duration (ly:make-duration dLog dDot
                            (* (/ (car dFac) (cdr dFac)) (/ num denom))))
                    scaledNote))))))

% Generate a rolled chord from the given notes. Each subsequent note is shifted
% by num/denom.
#(define genArpeggio (lambda (num denom notes)
    (if (pair? notes) ; Test for empty list
        ; Recursive case
        (if (null? (ly:music-property (car notes) 'duration))
            ; Skip objects that have no duration
            (genArpeggio (+ 1 num) denom (cdr notes))
            ; Shift notes
            (cons
                (shiftedNote num denom (car notes))
                (genArpeggio (+ 1 num) denom (cdr notes))))
        ; Base case
        '())))

% Params:
%   chord = The chord to arpeggiate.
%   denom = The fraction of the chord's length to use as a rest for each note
%       of the arpeggiated chord. This must not be less than the number of
%       notes in the chord. If it's greater than the number of chord notes, the
%       top note will be held longer.
midiArpeggio = #(define-music-function (denom chord) (number? ly:music?)
    (let ((chordTones (ly:music-property chord 'elements)))
        (make-music 'SimultaneousMusic
            'elements (genArpeggio 0 denom chordTones))))

% vim:set sw=4 ts=4 et:

%% by Harm
%% https://lists.gnu.org/archive/html/lilypond-user/2020-12/msg00039.html

getMidiArpeggios =
#(define-music-function (val mus) (number? ly:music?)
  (map-some-music
    (lambda (m)
      (and (music-is-of-type? m 'event-chord)
           (any
             (lambda (elt)
               (eq? (ly:music-property elt 'name) 'ArpeggioEvent))
             (ly:music-property m 'elements))
           (midiArpeggio val m)))
    mus))
    
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% EXAMPLES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

mus =
\new Staff \relative c' {
  <c e g c>4\arpeggio
  r2.
  |
  <c e g c>2
  <c e g c>\arpeggio
}
  
\score { \mus }

\score {
  \getMidiArpeggios 24
  \mus
  \midi { }
}

Reply via email to