Re: custom replace/map of one set of pitches to another

2023-09-01 Thread David Kastrup
Lukas-Fabian Moser  writes:

> Hi Valentin,
>
> Am 01.09.23 um 00:41 schrieb Valentin Petzel:
>> I don’t think this is a particularly good idea. Lilypond conceptually first
>> creates data for the sementic meaning of the music (or the actual content) 
>> and
>> have engravers turn this into graphical content.
>>
>> Mapping pitches to other pitches is not a layout option, but a musical
>> transformation and should thus be done on the music level, not the layout
>> level. Using an engraver will mean it is hard to combine this with other
>> musical transformations, and it will also cause order issues as soon as you
>> have an engraver that depends on the pitch property.
>
> I agree about the possible problems, and to be honest, I wasn't aware
> that a music function solution like yours can deal with \transpose and
> \relative gracefully (since the assignment of actual pitches is
> complete when the music function is applied on the outside).

Iff the music function is applied on the outside.

-- 
David Kastrup



Re: custom replace/map of one set of pitches to another

2023-09-01 Thread Lukas-Fabian Moser

Hi Valentin,

Am 01.09.23 um 00:41 schrieb Valentin Petzel:

I don’t think this is a particularly good idea. Lilypond conceptually first
creates data for the sementic meaning of the music (or the actual content) and
have engravers turn this into graphical content.

Mapping pitches to other pitches is not a layout option, but a musical
transformation and should thus be done on the music level, not the layout
level. Using an engraver will mean it is hard to combine this with other
musical transformations, and it will also cause order issues as soon as you
have an engraver that depends on the pitch property.


I agree about the possible problems, and to be honest, I wasn't aware 
that a music function solution like yours can deal with \transpose and 
\relative gracefully (since the assignment of actual pitches is complete 
when the music function is applied on the outside).


What I don't necessarily agree with is the philosophical notion of 
engravers being tied to the layout level (which is admittedly suggested 
by their name): As long as I work with listeners (as opposed to 
acknowledgers), I see no problem in using them for "semantic" 
transformations that need the music sorted by timestep (which 
nevertheless is not the case in the current situation).


Lukas




Re: custom replace/map of one set of pitches to another

2023-08-31 Thread Michael Winter via LilyPond user discussion
Thank you Valentin for this solution and the following explanation why it is 
likely safer.

All responses have been much appreciated.

Best,

Michael

Sep 1, 2023, 00:15 by valen...@petzel.at:

> Hi Michael,
>
> some time ago I created a function for exactly that for a stackexchange 
> question:
> https://music.stackexchange.com/questions/127175/lilypond-transpose-a-sequence-to-modes-with-different-intervallic-structure
>
> Essentially it introduces a function to map one scale to another, and it does 
> so by basepitch to retain alteration. One could easily adapt this function to 
> match by base pitch and alteration:
>
> transposePitchClasses =
> #(define-music-function (scaleA scaleB music) (ly:music? ly:music? ly:music?)
>  (let* ((scaleA (ly:music-property scaleA 'elements))
>  (scaleB (ly:music-property scaleB 'elements))
>  (scaleA (map (lambda (x) (ly:music-property x 'pitch)) scaleA))
>  (scaleB (map (lambda (x) (ly:music-property x 'pitch)) scaleB))
>  (classesA (map (lambda (p) (cons (ly:pitch-notename p) (ly:pitch-
> alteration p))) scaleA)))
>  (map-some-music
>  (lambda (m)
>  (let ((p (ly:music-property m 'pitch)))
>  (if (not (null? p))
>  (let* ((nn (ly:pitch-notename p))
>  (oct (ly:pitch-octave p))
>  (alt (ly:pitch-alteration p))
>  (pos (list-index (lambda (x) (and (= (car x) nn) (= (cdr x) 
> alt))) classesA)))
>  (if pos
>  (let* ((p2 (list-ref scaleA pos))
>  (oct2 (ly:pitch-octave p2))
>  (p3 (list-ref scaleB pos))
>  (new-pitch (ly:pitch-transpose p3 (ly:make-pitch (- 
> oct oct2) 0
>  (ly:music-set-property! m 'pitch new-pitch)))
>  m)
>  #f)))
>  music)
>  music))
>
> \transposePitchClasses {d fih g aih} {dih f gis a}
> { c' cis' d' dis' f' fih' fis' g' a' aih' }
>
> Am Donnerstag, 31. August 2023, 12:53:26 CEST schrieb Michael Winter via 
> LilyPond user discussion:
>
>> I would like to do something (hopefully simple), which is basically a custom
>> find and replace for a set of notes in an entire score.
>>
>> For example {c cis d dis fih g aih} -> {c cis dih dis f gis a}
>>
>> So basically on arbitrary list of pitches / scale  to another.
>>
>> Is this possible without writing a custom function. If not, any hints on how
>> to tackle the problem would be much appreciated. Thanks in advance.
>>
>> -Michael
>>



Re: custom replace/map of one set of pitches to another

2023-08-31 Thread Valentin Petzel
Hello Lukas,

I don’t think this is a particularly good idea. Lilypond conceptually first 
creates data for the sementic meaning of the music (or the actual content) and 
have engravers turn this into graphical content.

Mapping pitches to other pitches is not a layout option, but a musical 
transformation and should thus be done on the music level, not the layout 
level. Using an engraver will mean it is hard to combine this with other 
musical transformations, and it will also cause order issues as soon as you 
have an engraver that depends on the pitch property.

Cheers,
Valentin

Am Donnerstag, 31. August 2023, 14:35:45 CEST schrieb Lukas-Fabian Moser:
> Hi Michael,
> 
> over time, I found that doing something like this in an engraver (as
> opposed to a music function) is actually much easier and conceptually
> clear, in spite of the seeming difficulty of the engraver syntax. The
> advantage of using an engraver being that you see the "actual" pitches
> and don't have to fight with problems of \relative, \transpose and so on.
> 
> \version "2.24.0"
> 
> pitch-replace-dictionary =
> #(list
>(cons #{ c #} #{ cis #})
>(cons #{ d #} #{ des #})
>)
> 
> #(define (pitch-class= p q)
> (and
>  (= (ly:pitch-notename p) (ly:pitch-notename q))
>  (= (ly:pitch-alteration p) (ly:pitch-alteration q
> 
> Pitch_replace_engraver =
> #(lambda (context)
> (make-engraver
>  (listeners
>   ((note-event engraver event)
>(let*
> ((pitch (ly:event-property event 'pitch))
>  (rule (assoc pitch pitch-replace-dictionary pitch-class=)))
> 
> (if rule
> (ly:event-set-property!
>  event 'pitch
>  (ly:make-pitch (ly:pitch-octave pitch)
> (ly:pitch-notename (cdr rule))
> (ly:pitch-alteration (cdr rule))
> 
> \layout {
>\context {
>  \Score
>  \consists #Pitch_replace_engraver
>}
> }
> 
> \relative {
>c'4 d e c8 8
>\transpose f c \relative {
>  f'4 g a
>}
> }
> 
> This engraver can also be added to just a single score (\layout inside
> \score {}) or even a single Staff or Voice. At the moment, the
> replacement dictionary is global, but this could be changed if needed.
> 
> At the moment the mechanism I chose is too crude to do replacements that
> involve changing the pitch-octave (eg from c to b,). Do you need this?
> 
> Lukas
> 
> Am 31.08.23 um 12:53 schrieb Michael Winter via LilyPond user discussion:
> > I would like to do something (hopefully simple), which is basically a
> > custom find and replace for a set of notes in an entire score.
> > 
> > For example {c cis d dis fih g aih} -> {c cis dih dis f gis a}
> > 
> > So basically on arbitrary list of pitches / scale to another.
> > 
> > Is this possible without writing a custom function. If not, any hints
> > on how to tackle the problem would be much appreciated. Thanks in advance.
> > 
> > -Michael



signature.asc
Description: This is a digitally signed message part.


Re: custom replace/map of one set of pitches to another

2023-08-31 Thread Valentin Petzel
Hi Michael,

some time ago I created a function for exactly that for a stackexchange 
question:
https://music.stackexchange.com/questions/127175/lilypond-transpose-a-sequence-to-modes-with-different-intervallic-structure

Essentially it introduces a function to map one scale to another, and it does 
so by basepitch to retain alteration. One could easily adapt this function to 
match by base pitch and alteration:

transposePitchClasses =
#(define-music-function (scaleA scaleB music) (ly:music? ly:music? ly:music?)
   (let* ((scaleA (ly:music-property scaleA 'elements))
  (scaleB (ly:music-property scaleB 'elements))
  (scaleA (map (lambda (x) (ly:music-property x 'pitch)) scaleA))
  (scaleB (map (lambda (x) (ly:music-property x 'pitch)) scaleB))
  (classesA (map (lambda (p) (cons (ly:pitch-notename p) (ly:pitch-
alteration p))) scaleA)))
   (map-some-music
(lambda (m)
  (let ((p (ly:music-property m 'pitch)))
(if (not (null? p))
(let* ((nn (ly:pitch-notename p))
   (oct (ly:pitch-octave p))
   (alt (ly:pitch-alteration p))
   (pos (list-index (lambda (x) (and (= (car x) nn) (= (cdr x) 
alt))) classesA)))
  (if pos
  (let* ((p2 (list-ref scaleA pos))
 (oct2 (ly:pitch-octave p2))
 (p3 (list-ref scaleB pos))
 (new-pitch (ly:pitch-transpose p3 (ly:make-pitch (- 
oct oct2) 0
(ly:music-set-property! m 'pitch new-pitch)))
  m)
#f)))
music)
   music))

\transposePitchClasses {d fih g aih} {dih f gis a}
{ c' cis' d' dis' f' fih' fis' g' a' aih' }

Am Donnerstag, 31. August 2023, 12:53:26 CEST schrieb Michael Winter via 
LilyPond user discussion:
> I would like to do something (hopefully simple), which is basically a custom
> find and replace for a set of notes in an entire score.
> 
> For example {c cis d dis fih g aih} -> {c cis dih dis f gis a}
> 
> So basically on arbitrary list of pitches / scale  to another.
> 
> Is this possible without writing a custom function. If not, any hints on how
> to tackle the problem would be much appreciated. Thanks in advance.
> 
> -Michael



signature.asc
Description: This is a digitally signed message part.


Re: custom replace/map of one set of pitches to another

2023-08-31 Thread Michael Winter via LilyPond user discussion
That is very helpful. Thank you. I will ping again if I have any further 
questions.

Aug 31, 2023, 14:35 by l...@gmx.de:

> Hi Michael,
>
> over time, I found that doing something like this in an engraver (as opposed 
> to a music function) is actually much easier and conceptually clear, in spite 
> of the seeming difficulty of the engraver syntax. The advantage of using an 
> engraver being that you see the "actual" pitches and don't have to fight with 
> problems of \relative, \transpose and so on.
>
> \version "2.24.0"
>
> pitch-replace-dictionary =
> #(list
>   (cons #{ c #} #{ cis #})
>   (cons #{ d #} #{ des #})
>   )
>
> #(define (pitch-class= p q)
>    (and
>     (= (ly:pitch-notename p) (ly:pitch-notename q))
>     (= (ly:pitch-alteration p) (ly:pitch-alteration q
>
> Pitch_replace_engraver =
> #(lambda (context)
>    (make-engraver
>     (listeners
>  ((note-event engraver event)
>   (let*
>    ((pitch (ly:event-property event 'pitch))
>     (rule (assoc pitch pitch-replace-dictionary pitch-class=)))
>
>    (if rule
>    (ly:event-set-property!
>     event 'pitch
>     (ly:make-pitch (ly:pitch-octave pitch)
>    (ly:pitch-notename (cdr rule))
>    (ly:pitch-alteration (cdr rule))
>
> \layout {
>   \context {
>     \Score
>     \consists #Pitch_replace_engraver
>   }
> }
>
> \relative {
>   c'4 d e c8 8
>   \transpose f c \relative {
>     f'4 g a
>   }
> }
>
> This engraver can also be added to just a single score (\layout inside \score 
> {}) or even a single Staff or Voice. At the moment, the replacement 
> dictionary is global, but this could be changed if needed.
>
> At the moment the mechanism I chose is too crude to do replacements that 
> involve changing the pitch-octave (eg from c to b,). Do you need this?
>
> Lukas
>
> Am 31.08.23 um 12:53 schrieb Michael Winter via LilyPond user discussion:
>
>> I would like to do something (hopefully simple), which is basically a custom 
>> find and replace for a set of notes in an entire score.
>>
>> For example {c cis d dis fih g aih} -> {c cis dih dis f gis a}
>>
>> So basically on arbitrary list of pitches / scale to another.
>>
>> Is this possible without writing a custom function. If not, any hints on how 
>> to tackle the problem would be much appreciated. Thanks in advance.
>>
>> -Michael
>>



Re: custom replace/map of one set of pitches to another

2023-08-31 Thread Lukas-Fabian Moser

Hi Michael,

over time, I found that doing something like this in an engraver (as 
opposed to a music function) is actually much easier and conceptually 
clear, in spite of the seeming difficulty of the engraver syntax. The 
advantage of using an engraver being that you see the "actual" pitches 
and don't have to fight with problems of \relative, \transpose and so on.


\version "2.24.0"

pitch-replace-dictionary =
#(list
  (cons #{ c #} #{ cis #})
  (cons #{ d #} #{ des #})
  )

#(define (pitch-class= p q)
   (and
    (= (ly:pitch-notename p) (ly:pitch-notename q))
    (= (ly:pitch-alteration p) (ly:pitch-alteration q

Pitch_replace_engraver =
#(lambda (context)
   (make-engraver
    (listeners
 ((note-event engraver event)
  (let*
   ((pitch (ly:event-property event 'pitch))
    (rule (assoc pitch pitch-replace-dictionary pitch-class=)))

   (if rule
   (ly:event-set-property!
    event 'pitch
    (ly:make-pitch (ly:pitch-octave pitch)
   (ly:pitch-notename (cdr rule))
   (ly:pitch-alteration (cdr rule))

\layout {
  \context {
    \Score
    \consists #Pitch_replace_engraver
  }
}

\relative {
  c'4 d e c8 8
  \transpose f c \relative {
    f'4 g a
  }
}

This engraver can also be added to just a single score (\layout inside 
\score {}) or even a single Staff or Voice. At the moment, the 
replacement dictionary is global, but this could be changed if needed.


At the moment the mechanism I chose is too crude to do replacements that 
involve changing the pitch-octave (eg from c to b,). Do you need this?


Lukas

Am 31.08.23 um 12:53 schrieb Michael Winter via LilyPond user discussion:
I would like to do something (hopefully simple), which is basically a 
custom find and replace for a set of notes in an entire score.


For example {c cis d dis fih g aih} -> {c cis dih dis f gis a}

So basically on arbitrary list of pitches / scale to another.

Is this possible without writing a custom function. If not, any hints 
on how to tackle the problem would be much appreciated. Thanks in advance.


-Michael




Re: custom replace/map of one set of pitches to another

2023-08-31 Thread Michael Winter via LilyPond user discussion
I am now realizing that it would be useful to have this both at the level of 
the entire score and individually for each part.

Aug 31, 2023, 12:53 by mwin...@unboundedpress.org:

> I would like to do something (hopefully simple), which is basically a custom 
> find and replace for a set of notes in an entire score.
>
> For example {c cis d dis fih g aih} -> {c cis dih dis f gis a}
>
> So basically on arbitrary list of pitches / scale  to another.
>
> Is this possible without writing a custom function. If not, any hints on how 
> to tackle the problem would be much appreciated. Thanks in advance.
>
> -Michael
>