lilypond-user
[Top][All Lists]
Advanced

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

Re: Microtonal midi output


From: Jean Abou Samra
Subject: Re: Microtonal midi output
Date: Sun, 9 May 2021 10:06:07 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.8.1

Le 08/05/2021 à 23:50, Lukas-Fabian Moser a écrit :

Hi Jean,
(let* ((tones (ly:pitch-tones pitch))
                    (r (ly:moment-main
                         (ly:moment-mod
                           (ly:make-moment tones 0)
                           (ly:make-moment 6 0))))

... using LilyPond's moment-arithmetic (number on the time axis) to deal with non-integer tone counts (numbers on the pitch axis) seems to me like a reasonable contender for an obfuscated Lily coding contest. :-) But impressive it is.

It is a well-known trick… See
https://gitlab.com/lilypond/lilypond/-/issues/3139

Guile's modulo and remainder functions only
support integers, which is pitiful. Guile 2
brought an improvement with euclidean-quotient
and euclidean-remainder, which always yield a
positive remainder, and support rationals as well
as floats.

Maybe it's worth pointing out that your solution hardwires enharmonic identification (if I'm not mistaken). Of course I don't know what the OP intends to do, but in lots of real-life applications for re-tuning it's worth keeping the difference between f-sharp and g-flat alive.

Here is an enhanced version that stops enharmonic
identification, and copies the music before processing
it, to address Brahim's request.

\version "2.22.0"

tuneMIDI =
#(define-music-function (scale music) (list? ly:music?)
   (let ((copy (ly:music-deep-copy music)))
     (for-some-music
       (lambda (m)
         (let ((pitch (ly:music-property m 'pitch)))
           (if (ly:pitch? pitch)
               (let* ((note-name (ly:pitch-notename pitch))
                      (alteration (ly:pitch-alteration pitch))
                      (offset (assoc-ref scale
                                         (cons note-name alteration))))
                 (if offset
                     (let* ((transpose-pitch (ly:make-pitch 0 0 offset))
                            (new-pitch (ly:pitch-transpose pitch transpose-pitch)))
                       (ly:music-set-property! m 'pitch new-pitch)))))
           #f))
       copy)
     copy))

myNotes = \relative { a b c d e f gis aes a b c d e f gis aes a }

{ \myNotes }

\midi {
  \tempo 4 = 120
}

\score {
  \tuneMIDI
    #'(
       ; Lower F (index 3 in C major scale if 0 is C, no alteration) by 1/10 tone.
       ((3 . 0) . -1/10)
       ; Raise G# (index 4, sharp) by 1/10 tone.
       ((4 . 1/2) . 2/10)
       )
    \myNotes
  \midi { }
}

\score {
  \tuneMIDI
    #'(((3 . 0) . -1/10))
    \myNotes
  \midi { }
}


As Graham pointed out, LilyPond's habit of setting pitch bends before a note and re-setting it immediately after a note whose alteration is not in 1/2 * Z leads to strange effects with the release (or reverb) of a note. This can be observed in examples involving rests between re-tuned notes. I patched my LilyPond for this: Now it never explicitly resets MIDI pitch bends, instead each and every note gets a pitch-bend command. (Which would be crazy for most applications, but is fine for my special needs involving lots of re-tuned notes.) I didn't have time to find out how to make this user-configurable.

An option would be to go create an issue at
https://gitlab.com/lilypond/lilypond/-/issues
and attach your patch there, noting that it
is a work-in-progress and configurability should
be added. That way, someone might pick it up.

- I'm already looking forward to Graham's solution to this problem (post-processing the MIDI files using MTS messages.

I haven't tried it (understanding of MIDI is above
my pay grade), but it shoud certainly yield better
results.

Cheers,
Jean



reply via email to

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