Re: chord.ly to extract notes from chords breaks with new Guile
Better make that: > ``` > \version "2.24.1" > > #(define ((Keep_only_engraver i) context) > ``` > ``` #(define ((Keep_only_performer i) context) ``` > > ``` > (let ((j 0)) > (make-performer > (listeners >((note-event performer event) > (unless (eqv? i j) > (ly:event-set-property! event 'pitch #f)) > (set! j (1+ j > ((stop-translation-timestep performer) >(set! j 0) > > #(define (scores n music) >(apply values > (map (lambda (i) > #{ >\score { > \midi { \context { \Score \consists #(Keep_only_engraver > i) } } > ``` ``` \midi { \context { \Score \consists #(Keep_only_performer i) } } ``` > ``` > #music >} > #}) >(iota n > > mus = << > \new Staff { c'1 d'2 d'4 e'4 } > \new Staff << { g'1 a'2 a'4 b'4 } \\ { g1 g1 } >> > >> > > { \mus } > > $(scores 3 mus) % 3 is the max number of simutaneous notes > ``` (yay for muscle memory) signature.asc Description: This is a digitally signed message part
Re: chord.ly to extract notes from chords breaks with new Guile
Le mardi 30 mai 2023 à 20:39 -0400, msk...@ansuz.sooke.bc.ca a écrit : > I need, at each point in time, to have at most one note per track, exactly one > track per note, and silence in any leftover tracks, regardless of the > voice/chord structure of the music. That sounds like you want a performer-based approach. Like: ``` \version "2.24.1" #(define ((Keep_only_engraver i) context) (let ((j 0)) (make-performer (listeners ((note-event performer event) (unless (eqv? i j) (ly:event-set-property! event 'pitch #f)) (set! j (1+ j ((stop-translation-timestep performer) (set! j 0) #(define (scores n music) (apply values (map (lambda (i) #{ \score { \midi { \context { \Score \consists #(Keep_only_engraver i) } } #music } #}) (iota n mus = << \new Staff { c'1 d'2 d'4 e'4 } \new Staff << { g'1 a'2 a'4 b'4 } \\ { g1 g1 } >> >> { \mus } $(scores 3 mus) % 3 is the max number of simutaneous notes ``` signature.asc Description: This is a digitally signed message part
Re: chord.ly to extract notes from chords breaks with new Guile
On Wed, 31 May 2023, Gilles Thibault wrote: > Not hardly tested but this should work : Thanks for looking at it further. I hate to impose on you because I've already decided to solve this problem in external postprocessing of the MIDI files, so I hope you won't put a lot of effort into trying to satisfy my use case with modifications to your script. I don't think doing it in Lilypond is really the right solution for me because to really solve it I need to automatically handle *all* cases of simultaneous notes. I need, at each point in time, to have at most one note per track, exactly one track per note, and silence in any leftover tracks, regardless of the voice/chord structure of the music. The code you provide works for the specific example I gave, where the desired silence comes from a note written as a single note instead of a chord, but there are many other cases (illustrating the problem with minimal examples). In particular: * change b2 to 2 and the b2 comes out in two tracks. Maybe it would never occur to me to write a one-note chord, but a similar issue can happen between two- and three-note chords, or anywhere the number of notes per chord in a voice is not always the same. * a one-voice passage added outside the << >> construct comes out in two tracks * if each of two voices sometimes contains two simultaneous notes, but only at most three notes are simultaneous overall, then I need to either use four output tracks, or carefully split and then merge to bring it down to three, and handling this kind of thing becomes steadily more complicated as the number of voices and simultaneous notes grows. Resolving these points and any other similar ones that may come up, seems like a lot of work. If an in-Lilypond solution means I need to do things like maintain the same number of Voice contexts throughout the entire piece of music, or think hard about which note/voice index needs to merge with which other one to minimize the overall number of tracks without ever having more than one note simultaneous in a track, then we quickly approach a point where it would be less work for me to just write out the intended output by hand and not have Lilypond calculate it at all. In external MIDI processing it's relatively easy: at every "Note on" message in chronological order, I can route the note to an unused track or else know unambiguously that I need more tracks. At every "Note off," the track in question becomes available again. The external code basically does the same thing that a polyphonic synthesizer would do, just with output to new MIDI tracks instead of directly to hardware voices. No need for separate handling of Lilypond's "single note," "chord," and "voice" concepts. -- Matthew Skala msk...@ansuz.sooke.bc.ca People before tribes. https://ansuz.sooke.bc.ca/
Re: chord.ly to extract notes from chords breaks with new Guile
in the hope of separating MIDI notes that don't have identical timing. That is, if my input is << { a1 } \\ { b2 2 } >> it would be nice to be able to separate it out into three separate outputs for separate MIDI channels, like: { a1 } { b2 c2 } { r2 d2 } Not hardly tested but this should work : %%% \version "2.24.1" \include "chordsAndVoices.ly" noteAloneToRest = #(define-music-function (music)(ly:music?) (map-some-music (lambda(evt) (case (name-of evt) ;; see chordsAndVoices.ly ((EventChord) evt) ;; not #f => stop iteration ((NoteEvent) ;; note to rest (make-music 'RestEvent 'duration (ly:music-property evt 'duration '( (else #f)));; continue iteration music)) music = << { a1 } \\ { b2 2 } >> midiI = \extractVoice #1 \music midiII = \extractVoice #2 \extractNote #1 \music midiIII = \extractVoice #2 \extractNote #2 \noteAloneToRest \music \score { << \new Staff { \midiI } % { a1 } \new Staff { \midiII } % { b2 c2 } \new Staff { \midiIII } % { r2 d2 } % \midi } -- Gilles
Re: chord.ly to extract notes from chords breaks with new Guile
On Mon, 29 May 2023, Gilles Thibault wrote: > chord.ly has been renamed to chordsAndVoices.ly (it deals also now with > Voices) > You can donwload it here : Thanks a lot! As far as I know, the new version works fine. The problem in the old version was just because of the non-breaking spaces in the lines I modified according to instructions from the mailing list. That was a problem I encountered back in 2015 too, and thought I had fixed then. My version of the file is unmodified since 2015; evidently some non-breaking spaces survived the earlier fix, and earlier versions of Lilypond ignored them. I don't know why the latest version had a problem with these characters given that earlier versions didn't, but I also don't know why earlier versions *didn't* have a problem with these particular non-breaking spaces when others in the same file caused a lot of trouble. I will say again, as I said in 2015, that I wish people would stop trying to use HTML for email. That's where the non-breaking spaces came from. Anyway, even the old version of chord.ly contained support for separating voices, which I hadn't previously touched but I investigated just recently in the hope of separating MIDI notes that don't have identical timing. That is, if my input is << { a1 } \\ { b2 2 } >> it would be nice to be able to separate it out into three separate outputs for separate MIDI channels, like: { a1 } { b2 c2 } { r2 d2 } Unfortunately, both the old chord.ly and new chordsAndVoices.ly code have the same problem with respect to voices that I encountered in 2015 with respect to notes within a chord: requesting a non-existent voice index returns the last voice instead of silence. That seems to be the intended behaviour of the code in your application, so it's not exactly a bug, but it isn't what I need. I think the really right answer for me is to not use Lilypond to do this note-separation at all, but to do postprocessing with other tools on the MIDI files generated by Lilypond instead. I'm more confident of really getting correct results from that in all the different cases of simultaneous notes, than I would be by trying to do the separation inside Lilypond. -- Matthew Skala msk...@ansuz.sooke.bc.ca People before tribes. https://ansuz.sooke.bc.ca/
Re: chord.ly to extract notes from chords breaks with new Guile
Le 2023-05-27 22:31, msk...@ansuz.sooke.bc.ca a écrit : Back in 2015 people on the list helped me with extracting notes from chords, in this thread: https://lists.gnu.org/archive/html/lilypond-user/2015-09/msg00394.html chord.ly has been renamed to chordsAndVoices.ly (it deals also now with Voices) You can donwload it here : http://gillesth.free.fr/Lilypond/chordsAndVoices/ Note you have also to download checkPitch.ly to make it work. There is a small help http://gillesth.free.fr/Lilypond/chordsAndVoices/chordsAndVoices-doc.pdf I use chordsAndVoices.ly a lot, as it is part of the project arranger.ly http://gillesth.free.fr/Lilypond/arranger.ly/ My Lilypond version is 2.24.1 Please, tell me if there is something wrong with a more recent version. -- Gilles
Re: chord.ly to extract notes from chords breaks with new Guile
Le samedi 27 mai 2023 à 17:38 -0400, msk...@ansuz.sooke.bc.ca a écrit : > On Sat, 27 May 2023, Jean Abou Samra wrote: > > > Are you sure that this is the correct example? That the file chord.ly it > > uses is the same as the one you sent? That LilyPond is the one you believe > > and unpatched, etc. ? > > Yes, using the chord.ly file I attached to my message, extracted from the > message as it came back through the mailing list, with the three-line > input cut and pasted from my message as it came back through the mailing > list, and the version of Lilypond I compiled from the sources in the file > lilypond-2.24.1.tar.gz downloaded from the lilypond.org Web site, I get > these messages: > > GNU LilyPond 2.24.1 (running Guile 2.2) > Processing `test.ly' > Parsing...ERROR: In procedure %resolve-variable: > Unbound variable: #{ }# > > > I can't reproduce your problem (on Fedora); it compiles fine for me and > > prints a single MM rest. > > Interesting. What's the provenance of your Lilypond executable - did you > also compile from source, or use a Fedora package? > > I wonder if the issue could be with my Guile 2.2 installation, which I > also compiled from sources. I'm using Slackware, which does not have a > Guile 2.2 package, having skipped all the way to version 3. I had to > install Guile 2.2 over top of that in order to get a version of Lilypond > that would report itself as using Guile 2.2, but if the build was still > partly using Slackware's packaged Guile 3.0 somehow, that could explain > the difference in our results. As David pointed out, there are no-break spaces on lines 38 and 39, which you need to convert to normal spaces. Now I understand why I did not get the error; I use Frescobaldi, which apparently tried to be helpful (in this case a little too helpful) by auto-converting them. signature.asc Description: This is a digitally signed message part
Re: chord.ly to extract notes from chords breaks with new Guile
On Sat, 27 May 2023, David Kastrup wrote: > which contains a delirious number of unbreakable spaces, code \xa0 > instead of \x20 as for a normal, breakable space. Thanks! Correcting these seems to have fixed the problem, at least for the moment. I don't know why the old version needed *some* of the non-breaking spaces to be changed to regular spaces and did not require this of *all* of them, nor why the new version would be different. But that's not important. -- Matthew Skala msk...@ansuz.sooke.bc.ca People before tribes. https://ansuz.sooke.bc.ca/
Re: chord.ly to extract notes from chords breaks with new Guile
On Sat, 27 May 2023, Jean Abou Samra wrote: > Are you sure that this is the correct example? That the file chord.ly it > uses is the same as the one you sent? That LilyPond is the one you believe > and unpatched, etc. ? Yes, using the chord.ly file I attached to my message, extracted from the message as it came back through the mailing list, with the three-line input cut and pasted from my message as it came back through the mailing list, and the version of Lilypond I compiled from the sources in the file lilypond-2.24.1.tar.gz downloaded from the lilypond.org Web site, I get these messages: GNU LilyPond 2.24.1 (running Guile 2.2) Processing `test.ly' Parsing...ERROR: In procedure %resolve-variable: Unbound variable: #{ }# > I can't reproduce your problem (on Fedora); it compiles fine for me and > prints a single MM rest. Interesting. What's the provenance of your Lilypond executable - did you also compile from source, or use a Fedora package? I wonder if the issue could be with my Guile 2.2 installation, which I also compiled from sources. I'm using Slackware, which does not have a Guile 2.2 package, having skipped all the way to version 3. I had to install Guile 2.2 over top of that in order to get a version of Lilypond that would report itself as using Guile 2.2, but if the build was still partly using Slackware's packaged Guile 3.0 somehow, that could explain the difference in our results. -- Matthew Skala msk...@ansuz.sooke.bc.ca People before tribes. https://ansuz.sooke.bc.ca/
Re: chord.ly to extract notes from chords breaks with new Guile
msk...@ansuz.sooke.bc.ca writes: > Here's a small example showing the problem: > > \include "chord.ly" > music = { 1 } > { \extractNote #3 \music } > > In version 2.21.0 that produces a whole-note rest. In version 2.24.1 with > Guile 2.2 it gives this error output: > > GNU LilyPond 2.24.1 (running Guile 2.2) > Processing `test.ly' > Parsing...ERROR: In procedure %resolve-variable: > Unbound variable: #{ }# > > Lilypond 2.24.1 compiled with Guile 3.0.9 also gives this error. > > I attach the version of chord.ly I'm using, which I got from the 2015 > discussion. I found these links helpful at that time and I think one of > them contained the original for this version of chord.ly: > http://gillesth.free.fr/Lilypond/chord/ > http://www.lilypondforum.de/index.php?topic=2080.msg11479#msg11479 Your way of "getting chord.ly from the 2015 discussion" is broken. To wit, it contains a line ((null? res) (let ((note (list-ref notes (1- len ; last note (make-music 'RestEvent 'duration (ly:music-property note 'duration which contains a delirious number of unbreakable spaces, code \xa0 instead of \x20 as for a normal, breakable space. Both Guile and LilyPond treat the unbreakable space as a normal character instead of a space character. Please fix your input file to stop containing unbreakable space characters and also make sure that the comment ; last note is not continued with unbreakable space characters into further code which turns it into a no-show for Guile. Once you fix your unbreakable space as well as missing linebreak after comment problems, things will likely look more normal. -- David Kastrup
Re: chord.ly to extract notes from chords breaks with new Guile
Le samedi 27 mai 2023 à 16:31 -0400, msk...@ansuz.sooke.bc.ca a écrit : > Here's a small example showing the problem: > > \include "chord.ly" > music = { 1 } > { \extractNote #3 \music } > > In version 2.21.0 that produces a whole-note rest. In version 2.24.1 with > Guile 2.2 it gives this error output: > > GNU LilyPond 2.24.1 (running Guile 2.2) > Processing `test.ly' > Parsing...ERROR: In procedure %resolve-variable: > Unbound variable: #{ }# > > Lilypond 2.24.1 compiled with Guile 3.0.9 also gives this error. Are you sure that this is the correct example? That the file chord.ly it uses is the same as the one you sent? That LilyPond is the one you believe and unpatched, etc. ? I can't reproduce your problem (on Fedora); it compiles fine for me and prints a single MM rest. signature.asc Description: This is a digitally signed message part
chord.ly to extract notes from chords breaks with new Guile
Back in 2015 people on the list helped me with extracting notes from chords, in this thread: https://lists.gnu.org/archive/html/lilypond-user/2015-09/msg00394.html The solution from 2015 has broken now, in the transition between versions 2.21.0 and 2.24.1. I think it's because of changes in Guile 2.2. I haven't had the opportunity to test with versions strictly between 2.21.0 and 2.24.1. My situation is that I have music containing chords which I want to play on a monophonic synthesizer, by generating separate MIDI tracks such that in each track there is only one note playing at a time. After recording the tracks separately I'll mix the audio files. So I'd like to have a function I can call that takes in music with multi-note chords and selects just one note from each chord. Making it a little more complicated, the number of notes in the chords varies, including some single notes that Lilypond may represent internally as different from "chords." I need to generate as many tracks as the maximum number of notes that will play simultaneously, but have silence in the extra tracks at times when there are fewer notes playing than there are tracks. So, for instance, if my input looks like { c4 4 4 } then I want to generate tracks that might look like { c4 c4 c4 } { r4 e4 e4 } { r4 r4 g4 } It's not important which tracks get which notes and which tracks get silence; all that matters is that the union of the output tracks should be the same notes that were in the input, with silence assigned to unused tracks. It would be nice if it could handle more complicated structures of overlapping notes like << { c2 } { d4 e4 } >> but the solution I've been using since 2015 doesn't, there are some foreseeable problems with doing that in the general case, and it's not my main concern right now. The main issue is that I want my existing files that work to continue working in more recent Lilypond. This is a near-dealbreaker for me using a more recent Lilypond at all - I could and might fix it by just sticking to 2.21.0 indefinitely - but I'd really like to also be able to override midiDrumPitches, which seems to be new in some version more recent than 2.21. Here's a small example showing the problem: \include "chord.ly" music = { 1 } { \extractNote #3 \music } In version 2.21.0 that produces a whole-note rest. In version 2.24.1 with Guile 2.2 it gives this error output: GNU LilyPond 2.24.1 (running Guile 2.2) Processing `test.ly' Parsing...ERROR: In procedure %resolve-variable: Unbound variable: #{ }# Lilypond 2.24.1 compiled with Guile 3.0.9 also gives this error. I attach the version of chord.ly I'm using, which I got from the 2015 discussion. I found these links helpful at that time and I think one of them contained the original for this version of chord.ly: http://gillesth.free.fr/Lilypond/chord/ http://www.lilypondforum.de/index.php?topic=2080.msg11479#msg11479 but those links are both dead now, making it difficult for me to figure out exactly which changes I applied to get it to work in 2015. The version currently in LSR snippet number 545 does not give the unbound variable error, but it is dated earlier, and it has the problem for which I started the 2015 thread: on an out-of-range index it just returns the last note (d in my example) instead of returning silence. The present error output seems to be specific to the case of extracting a note that doesn't exist, such as the third note of a two-note chord in my example. It works without error if I only ask for notes that exist. However, I can't really avoid giving an out-of-range index; being able to do that and get silence is a big part of the point of the exercise. -- Matthew Skala msk...@ansuz.sooke.bc.ca People before tribes. https://ansuz.sooke.bc.ca/%% version Y/M/D = 2015/03/23 %% LSR = http://lsr.di.unimi.it/LSR/Item?u=1=761 %% LSR = http://lsr.di.unimi.it/LSR/Item?u=1=545 %% for Lilypond 2.16 or higher. %% last major change in extract-note function : as \tuplet as now %% a 'duration property, we have to deal with this special case. %% by chord->note. You can now specified several numbers, to %% extract several notes at one time #(define (noteEvent? music) (eq? (ly:music-property music 'name) 'NoteEvent)) #(define (no-duration? music) (not (ly:duration? (ly:music-property music 'duration #(define (expand-q-chords music); for q chords : see chord-repetition-init.ly (expand-repeat-chords! (list 'rhythmic-event) music)) %% extractNote % #(define tagNotExtractNote (gensym)) #(use-modules (ice-9 receive)) %% for the use of receive #(define (chord->note chord n . args) "Return either the note n of chord chord, keeping articulations or if other numbers are specified in args, a chord with the matching notes." (receive (notes others) (partition noteEvent? (ly:music-property chord 'elements)) (if (null? notes) chord (let* ((len (length