Re: chord.ly to extract notes from chords breaks with new Guile

2023-06-01 Thread Jean Abou Samra
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

2023-05-30 Thread Jean Abou Samra
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

2023-05-30 Thread mskala
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

2023-05-30 Thread Gilles Thibault




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

2023-05-29 Thread mskala
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

2023-05-29 Thread Gilles Thibault

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

2023-05-27 Thread Jean Abou Samra
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

2023-05-27 Thread mskala
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

2023-05-27 Thread mskala
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

2023-05-27 Thread David Kastrup
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

2023-05-27 Thread Jean Abou Samra
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

2023-05-27 Thread mskala
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