Re: Automatic cross-staff chords - testing help

2021-01-10 Thread Davide Bonetti

woops, I used % instead of ; in scheme

here the right code :)

Davide

\version "2.20.0"

#(define (split-music dir music ref)
   (let ((es (ly:music-property music 'elements))
 (e (ly:music-property music 'element))
 (p (ly:music-property music 'pitch)))
 (if (pair? es)
 (ly:music-set-property!
  music 'elements
  (map (lambda (x) (split-music dir x ref)) es)))
 (if (ly:music? e)
 (ly:music-set-property!
  music 'element
  (split-music dir e ref)))
 (if (ly:pitch? p)
 (if ((if (> dir 0) >= <)
  (ly:pitch-steps p) (ly:pitch-steps ref))
 p
 (ly:music-set-property! music 'name 'SkipEvent) ; works, 
but produces warnings

 ))
 music
 ))

splitMusic =
#(define-music-function (parser location dir ref music )
   ((ly:dir? 1) (ly:pitch? (ly:make-pitch 0 0)) ly:music? )
   (split-music dir music ref))

Il 10/01/2021 22:12, Davide Bonetti ha scritto:

I did it!

the code works, but produces warnings.

Cheers

Davide

\version "2.20.0"

#(define (split-music dir music ref)
   (let ((es (ly:music-property music 'elements))
 (e (ly:music-property music 'element))
 (p (ly:music-property music 'pitch)))
 (if (pair? es)
 (ly:music-set-property!
  music 'elements
  (map (lambda (x) (split-music dir x ref)) es)))
 (if (ly:music? e)
 (ly:music-set-property!
  music 'element
  (split-music dir e ref)))
 (if (ly:pitch? p)
 (if ((if (> dir 0) >= <)
  (ly:pitch-steps p) (ly:pitch-steps ref))
 p
 (ly:music-set-property! music 'name 'SkipEvent) ; works, 
but produces warnings

 ))
 music
 ))

splitMusic =
#(define-music-function (parser location dir ref music )
   ((ly:dir? 1) (ly:pitch? (ly:make-pitch 0 0)) ly:music? )
   (split-music dir music ref))

%%%
%Examples

someMusic = {
  c d e g c' d' c''
  
  \chordmode{d:7/a}
  << {c' d' e' f'} \\ {c d e f}>>
  d'2.
  \relative c' {c1 b a g}
  << \chordmode { c4 d e f} \\ \transpose c c, \chordmode {c d e f}>>
  << {c' b e' f'} \\ {c, e, c2} \\ {g2 a4 b}>>
}

\markup "Some music"
{\someMusic}

\markup "\SplitMusic result on piano staff"
\new PianoStaff
<<
  \new Staff {\splitMusic \someMusic}
  \new Staff {
    \clef bass
    \splitMusic #DOWN \someMusic
  }
>>

\markup "\SplitMusic result on SATB (with arbitrary split-points)"
\new StaffGroup
<<
  \new Staff {
    \clef soprano
    \splitMusic #UP f' \someMusic
  }
  \new Staff {
    \clef alto
    \splitMusic #DOWN f' \splitMusic #UP a \someMusic
  }
  \new Staff {
    \clef tenor
    \splitMusic #DOWN a \splitMusic #UP d \someMusic
  }
  \new Staff {
    \clef baritone
    \splitMusic #DOWN d \someMusic
  }
>>


Il 08/01/2021 00:55, Thomas Morley ha scritto:
Am Do., 7. Jan. 2021 um 13:08 Uhr schrieb Davide Bonetti 
:

Hi,

Great work.

I've done some testing and found some bugs. Below the code I've tested,
attached the PDF with the result (on second page, first page are your
examples).

\autoSplitChord doesn't works with curly braces, it returns blank 
output

(like a blank space in the score), so it's not possible to work with:
- chordmode
- more than one chord a time
- moltiple voices

Also, \autoSplitChord doesn't works with single notes, it returns blank
space.

It accepts variables, but the result is the same.

Pippo = 1
PippoDue = \chordmode {c1:/g}
PippoTre = c1
PippoQuattro = {}

\new PianoStaff
\with { \consists #Span_stem_engraver }
<<
    \new Staff = "up"
    {
  \key c\major
  %chord with stem up
  \autoSplitChord #UP 2 %works
  %chord without stem
  \autoSplitChord 4    %works
  %chord with stem down
  \autoSplitChord #DOWN     %works
  %chord, whole note
  \autoSplitChord 1    %works
  %chordmode
  \autoSplitChord \chordmode {c:/g} %blank output
  %chord entered in curly braces
  \autoSplitChord {} %blank output
  %more than one chord, in curly braces
  \autoSplitChord { } %blank output
  %single note
  \autoSplitChord c %blank output
  %single note in a chord
  \autoSplitChord     %works
  %chord entered in polyphonic style
  \autoSplitChord <> %works
  %polyphonic style, different durations
  \autoSplitChord <> %warning & strange output
  %polyphonic style, with some curly braces
  \autoSplitChord <> %notes in curly braces are
not printed
  %polyphonic style, with curly braces
  \autoSplitChord <<
    {c4 d e f}
    \\
    {c' d' e' f'}
  >>    %blank output
  %chord in a variable
  \autoSplitChord \Pippo    %works
  %chord in a variable with chordmode
  \autoSplitChord \PippoDue    %blank output
  %single note in a variable
  \autoSplitChord \PippoTre    

Re: Automatic cross-staff chords - testing help

2021-01-10 Thread Davide Bonetti

I did it!

the code works, but produces warnings.

Cheers

Davide

\version "2.20.0"

#(define (split-music dir music ref)
   (let ((es (ly:music-property music 'elements))
 (e (ly:music-property music 'element))
 (p (ly:music-property music 'pitch)))
 (if (pair? es)
 (ly:music-set-property!
  music 'elements
  (map (lambda (x) (split-music dir x ref)) es)))
 (if (ly:music? e)
 (ly:music-set-property!
  music 'element
  (split-music dir e ref)))
 (if (ly:pitch? p)
 (if ((if (> dir 0) >= <)
  (ly:pitch-steps p) (ly:pitch-steps ref))
 p
 (ly:music-set-property! music 'name 'SkipEvent) % works, 
but produces warnings

 ))
 music
 ))

splitMusic =
#(define-music-function (parser location dir ref music )
   ((ly:dir? 1) (ly:pitch? (ly:make-pitch 0 0)) ly:music? )
   (split-music dir music ref))

%%%
%Examples

someMusic = {
  c d e g c' d' c''
  
  \chordmode{d:7/a}
  << {c' d' e' f'} \\ {c d e f}>>
  d'2.
  \relative c' {c1 b a g}
  << \chordmode { c4 d e f} \\ \transpose c c, \chordmode {c d e f}>>
  << {c' b e' f'} \\ {c, e, c2} \\ {g2 a4 b}>>
}

\markup "Some music"
{\someMusic}

\markup "\SplitMusic result on piano staff"
\new PianoStaff
<<
  \new Staff {\splitMusic \someMusic}
  \new Staff {
    \clef bass
    \splitMusic #DOWN \someMusic
  }
>>

\markup "\SplitMusic result on SATB (with arbitrary split-points)"
\new StaffGroup
<<
  \new Staff {
    \clef soprano
    \splitMusic #UP f' \someMusic
  }
  \new Staff {
    \clef alto
    \splitMusic #DOWN f' \splitMusic #UP a \someMusic
  }
  \new Staff {
    \clef tenor
    \splitMusic #DOWN a \splitMusic #UP d \someMusic
  }
  \new Staff {
    \clef baritone
    \splitMusic #DOWN d \someMusic
  }
>>


Il 08/01/2021 00:55, Thomas Morley ha scritto:

Am Do., 7. Jan. 2021 um 13:08 Uhr schrieb Davide Bonetti 
:

Hi,

Great work.

I've done some testing and found some bugs. Below the code I've tested,
attached the PDF with the result (on second page, first page are your
examples).

\autoSplitChord doesn't works with curly braces, it returns blank output
(like a blank space in the score), so it's not possible to work with:
- chordmode
- more than one chord a time
- moltiple voices

Also, \autoSplitChord doesn't works with single notes, it returns blank
space.

It accepts variables, but the result is the same.

Pippo = 1
PippoDue = \chordmode {c1:/g}
PippoTre = c1
PippoQuattro = {}

\new PianoStaff
\with { \consists #Span_stem_engraver }
<<
\new Staff = "up"
{
  \key c\major
  %chord with stem up
  \autoSplitChord #UP 2 %works
  %chord without stem
  \autoSplitChord 4%works
  %chord with stem down
  \autoSplitChord #DOWN %works
  %chord, whole note
  \autoSplitChord 1%works
  %chordmode
  \autoSplitChord \chordmode {c:/g} %blank output
  %chord entered in curly braces
  \autoSplitChord {} %blank output
  %more than one chord, in curly braces
  \autoSplitChord { }  %blank output
  %single note
  \autoSplitChord c %blank output
  %single note in a chord
  \autoSplitChord %works
  %chord entered in polyphonic style
  \autoSplitChord <>%works
  %polyphonic style, different durations
  \autoSplitChord <>%warning & strange output
  %polyphonic style, with some curly braces
  \autoSplitChord <>%notes in curly braces are
not printed
  %polyphonic style, with curly braces
  \autoSplitChord <<
{c4 d e f}
\\
{c' d' e' f'}
  >>%blank output
  %chord in a variable
  \autoSplitChord \Pippo%works
  %chord in a variable with chordmode
  \autoSplitChord \PippoDue%blank output
  %single note in a variable
  \autoSplitChord \PippoTre%blank output
  %chord in curly braces in a variable
  \autoSplitChord \PippoQuattro%blank output
}
\new Staff = "down"
{
  \key c\major
  \clef bass
  s1
}
  >>

Thank you for the work.

Cheers

Davide

Hi Davide,

many thanks for testing.

Though, `autoSplitChord` is meant ot be a tool applied to chords, i.e.
event-chords.
All of:
\chordmode { c:/g }
{  }
<<
   {c4 d e f}
   \\
   {c' d' e' f'}
is sequential or simultaneous music.
A single note-event like c'4 is not an event-chord as well.

In all those cases `autoSplitChord` is not expected to work.
\autoSplitChord << b \\ e' \\ g'' >> works more by accident.

Below is an improved function which will simply returns the input, if
it's not an event-chord, avoiding the blank space.
\autoSplitChord << b \\ e' \\ g'' >> will stop working as well, all
notes are returned unchanged.

autoSplitChord =
#(define-music-function (stem-dir staff-names pitch chord)
   ((ly:dir? 0) (pair? 

re: Automatic cross-staff chords - testing help

2021-01-09 Thread Davide Bonetti

Update:

\autoSplitChord \chordmode { c:/g}

doesn't work, but:

\chordmode { \autoSplitChord c:/g}

works.

So, if we can make \autoSplitChord accept sequences of music, that can 
include chords or succession of chords, we'll have  our goal.


Cheers

Davide


--
Questa e-mail è stata controllata per individuare virus con Avast antivirus.
https://www.avast.com/antivirus




Re: Automatic cross-staff chords - testing help

2021-01-08 Thread Davide Bonetti

Hi Harm,


many thanks for testing.

thanks to you for the reply.


Below is an improved function which will simply returns the input, if
it's not an event-chord, avoiding the blank space.
\autoSplitChord << b \\ e' \\ g'' >> will stop working as well, all
notes are returned unchanged.

I see you've put an if condition to exclude input that is not event-chord.

There is now a problem: the below staff  is not printed when there is 
not an event-chord, and when an event-chord returns, a new staff is 
printed (with treble clef).


Pippo = 1
PippoDue = \chordmode {c1:/g}
PippoTre = c1
PippoQuattro = {}

\new PianoStaff
\with { \consists #Span_stem_engraver }
<<
  \new Staff = "up"
  {
    \key c\major
    \autoSplitChord #UP 2
    \autoSplitChord 4
    \autoSplitChord #DOWN 
    \autoSplitChord 1
    \autoSplitChord \chordmode {c:/g}
    \autoSplitChord {}
    \autoSplitChord { }
    \autoSplitChord c
    \autoSplitChord 
    \autoSplitChord <>
    \autoSplitChord <>
    \autoSplitChord <>
    \autoSplitChord <<
  {c4 d e f}
  \\
  {c' d' e' f'}
    >>
    \autoSplitChord \Pippo
    \autoSplitChord \PippoDue
    \autoSplitChord \PippoTre
    \autoSplitChord \PippoQuattro
  }
  \new Staff = "down"
  {
    \key c\major
    \clef bass
    s1 %bass staff appear only at the beginning, then reappears as 
another staff with treble clef

  }
>>

To avoid the problem, one can declare the lenght of the bass staff:

[...]
  \new Staff = "down"
  {
    \key c\major
    \clef bass
    \repeat unfold 16 s1 %bass staff is shown correctly
  }
>>

As shown in the attached files.

Perhaps there is a method to let the second staff to be printed without 
having to declare it's lenght.



\autoSplitChord is supposed to work on a single chord of a single
Voice. Like \autochange works an single notes of  a single Voice.
Maybe there's a recursive (or something similar) method so 
\autoSplitChord can work with chord sequences.

\autochange accepts sequential input.


Best would be a combination, I'll continue thinking about it.


Me too. Scheme is not so intuitive for me, but sometimes I find a solution.

Thank you

Davide





--
Questa e-mail è stata controllata per individuare virus con Avast antivirus.
https://www.avast.com/antivirus

\version "2.20.0"

#(define (make-autosplit-chord chord . ref-pitch)
   "Return a pair of lists, containing the pitches of @var{chord}, splitted at
a reference pitch.  The reference pitch is derived from @var{ref-pitch}.
If @var{ref-pitch} is empty, @code{c'} is regarded as reference.
  "
   (define ref-pitch-steps
 (if (and (pair? ref-pitch) (car ref-pitch))
 (ly:pitch-steps (car ref-pitch))
 0))

   (call-with-values
(lambda ()
  (partition
   (lambda (note)
 (> (ly:pitch-steps (ly:music-property note 'pitch))
ref-pitch-steps))
   (event-chord-notes chord)))
(lambda (x y) (cons x y

autoSplitChord =
#(define-music-function (stem-dir staff-names pitch chord)
   ((ly:dir? 0) (pair? '("up" . "down")) (ly:pitch?) ly:music?)
   (_i "Split @var{chord} at optional @var{pitch}.  The default of @var{pitch} is
@code{#f}, which is interpreted by the called procedure
@code{make-autosplit-chord} as @code{c'}.

The splitted chords are distributed to named staves, relying on optional
@var{staff-names}.

The optional @var{stem-dir}, determines the direction of the stems and whether
the chords may be connected by a cross-staff stem.
The default results in unconnected chords.
If the @code{Span_stem_engraver} is consisted, the chords may be connected by a
cross-staff stem.")
   (if (music-is-of-type? chord 'event-chord)
   (let* ((skip (make-duration-of-length (ly:music-length chord)))
  (devided-pitches (make-autosplit-chord chord pitch))
  (upper-chord
   (if (pair? (car devided-pitches))
   (make-event-chord (car devided-pitches))
   (make-skip-music skip)))
  (lower-chord
   (if (pair? (cdr devided-pitches))
   (make-event-chord (cdr devided-pitches))
   (make-skip-music skip
 #{
   <<
 \context Staff = #(car staff-names)
 \context Voice {
   $(if (negative? stem-dir)
#{
  \once \override Stem.cross-staff = #cross-staff-connect
  \once \override Flag.style = #'no-flag
  <>\noBeam
#})
   $(if (not (zero? stem-dir))
#{ \once \override Stem.direction = #stem-dir #})
   #upper-chord
 }

 \context Staff = #(cdr staff-names)
 \context Voice {
   $(if (positive? stem-dir)
#{
  \once \override Stem.cross-staff = #cross-staff-connect
  \once \override Flag.style = #'no-flag
  <>\noBeam
 

Re: Automatic cross-staff chords - testing help

2021-01-07 Thread Thomas Morley
Am Do., 7. Jan. 2021 um 13:08 Uhr schrieb Davide Bonetti 
:
>
> Hi,
>
> Great work.
>
> I've done some testing and found some bugs. Below the code I've tested,
> attached the PDF with the result (on second page, first page are your
> examples).
>
> \autoSplitChord doesn't works with curly braces, it returns blank output
> (like a blank space in the score), so it's not possible to work with:
> - chordmode
> - more than one chord a time
> - moltiple voices
>
> Also, \autoSplitChord doesn't works with single notes, it returns blank
> space.
>
> It accepts variables, but the result is the same.
>
> Pippo = 1
> PippoDue = \chordmode {c1:/g}
> PippoTre = c1
> PippoQuattro = {}
>
> \new PianoStaff
> \with { \consists #Span_stem_engraver }
> <<
>\new Staff = "up"
>{
>  \key c\major
>  %chord with stem up
>  \autoSplitChord #UP 2 %works
>  %chord without stem
>  \autoSplitChord 4%works
>  %chord with stem down
>  \autoSplitChord #DOWN %works
>  %chord, whole note
>  \autoSplitChord 1%works
>  %chordmode
>  \autoSplitChord \chordmode {c:/g} %blank output
>  %chord entered in curly braces
>  \autoSplitChord {} %blank output
>  %more than one chord, in curly braces
>  \autoSplitChord { }  %blank output
>  %single note
>  \autoSplitChord c %blank output
>  %single note in a chord
>  \autoSplitChord %works
>  %chord entered in polyphonic style
>  \autoSplitChord <>%works
>  %polyphonic style, different durations
>  \autoSplitChord <>%warning & strange output
>  %polyphonic style, with some curly braces
>  \autoSplitChord <>%notes in curly braces are
> not printed
>  %polyphonic style, with curly braces
>  \autoSplitChord <<
>{c4 d e f}
>\\
>{c' d' e' f'}
>  >>%blank output
>  %chord in a variable
>  \autoSplitChord \Pippo%works
>  %chord in a variable with chordmode
>  \autoSplitChord \PippoDue%blank output
>  %single note in a variable
>  \autoSplitChord \PippoTre%blank output
>  %chord in curly braces in a variable
>  \autoSplitChord \PippoQuattro%blank output
>}
>\new Staff = "down"
>{
>  \key c\major
>  \clef bass
>  s1
>}
>  >>
>
> Thank you for the work.
>
> Cheers
>
> Davide

Hi Davide,

many thanks for testing.

Though, `autoSplitChord` is meant ot be a tool applied to chords, i.e.
event-chords.
All of:
\chordmode { c:/g }
{  }
<<
  {c4 d e f}
  \\
  {c' d' e' f'}
>>
is sequential or simultaneous music.
A single note-event like c'4 is not an event-chord as well.

In all those cases `autoSplitChord` is not expected to work.
\autoSplitChord << b \\ e' \\ g'' >> works more by accident.

Below is an improved function which will simply returns the input, if
it's not an event-chord, avoiding the blank space.
\autoSplitChord << b \\ e' \\ g'' >> will stop working as well, all
notes are returned unchanged.

autoSplitChord =
#(define-music-function (stem-dir staff-names pitch chord)
  ((ly:dir? 0) (pair? '("up" . "down")) (ly:pitch?) ly:music?)
  (_i "Split @var{chord} at optional @var{pitch}.  The default of @var{pitch} is
@code{#f}, which is interpreted by the called procedure
@code{make-autosplit-chord} as @code{c'}.

The splitted chords are distributed to named staves, relying on optional
@var{staff-names}.

The optional @var{stem-dir}, determines the direction of the stems and whether
the chords may be connected by a cross-staff stem.
The default results in unconnected chords.
If the @code{Span_stem_engraver} is consisted, the chords may be connected by a
cross-staff stem.")
  (if (music-is-of-type? chord 'event-chord)
  (let* ((skip (make-duration-of-length (ly:music-length chord)))
 (devided-pitches (make-autosplit-chord chord pitch))
 (upper-chord
   (if (pair? (car devided-pitches))
   (make-event-chord (car devided-pitches))
   (make-skip-music skip)))
 (lower-chord
   (if (pair? (cdr devided-pitches))
   (make-event-chord (cdr devided-pitches))
   (make-skip-music skip
#{
  <<
\context Staff = #(car staff-names)
  \context Voice {
$(if (negative? stem-dir)
  #{
 \once \override Stem.cross-staff = #cross-staff-connect
 \once \override Flag.style = #'no-flag
 <>\noBeam
  #})
$(if (not (zero? stem-dir))
  #{ \once \override Stem.direction = #stem-dir #})
#upper-chord
  }

\context Staff = #(cdr staff-names)
  \context Voice {
$(if (positive? stem-dir)
  #{
   

Automatic cross-staff chords - testing help

2021-01-07 Thread Davide Bonetti

Hi,

Great work.

I've done some testing and found some bugs. Below the code I've tested, 
attached the PDF with the result (on second page, first page are your 
examples).


\autoSplitChord doesn't works with curly braces, it returns blank output 
(like a blank space in the score), so it's not possible to work with:

- chordmode
- more than one chord a time
- moltiple voices

Also, \autoSplitChord doesn't works with single notes, it returns blank 
space.


It accepts variables, but the result is the same.

Pippo = 1
PippoDue = \chordmode {c1:/g}
PippoTre = c1
PippoQuattro = {}

\new PianoStaff
\with { \consists #Span_stem_engraver }
<<
  \new Staff = "up"
  {
    \key c\major
    %chord with stem up
    \autoSplitChord #UP 2         %works
    %chord without stem
    \autoSplitChord 4            %works
    %chord with stem down
    \autoSplitChord #DOWN         %works
    %chord, whole note
    \autoSplitChord 1        %works
    %chordmode
    \autoSplitChord \chordmode {c:/g}         %blank output
    %chord entered in curly braces
    \autoSplitChord {}         %blank output
    %more than one chord, in curly braces
    \autoSplitChord { }  %blank output
    %single note
    \autoSplitChord c                 %blank output
    %single note in a chord
    \autoSplitChord             %works
    %chord entered in polyphonic style
    \autoSplitChord <>        %works
    %polyphonic style, different durations
    \autoSplitChord <>    %warning & strange output
    %polyphonic style, with some curly braces
    \autoSplitChord <>    %notes in curly braces are 
not printed

    %polyphonic style, with curly braces
    \autoSplitChord <<
  {c4 d e f}
  \\
  {c' d' e' f'}
    >>                        %blank output
    %chord in a variable
    \autoSplitChord \Pippo            %works
    %chord in a variable with chordmode
    \autoSplitChord \PippoDue            %blank output
    %single note in a variable
    \autoSplitChord \PippoTre            %blank output
    %chord in curly braces in a variable
    \autoSplitChord \PippoQuattro        %blank output
  }
  \new Staff = "down"
  {
    \key c\major
    \clef bass
    s1
  }
>>

Thank you for the work.

Cheers

Davide



--
Questa e-mail è stata controllata per individuare virus con Avast antivirus.
https://www.avast.com/antivirus

\version "2.20.0"

#(define (make-autosplit-chord chord . ref-pitch)
   "Return a pair of lists, containing the pitches of @var{chord}, splitted at
a reference pitch.  The reference pitch is derived from @var{ref-pitch}.
If @var{ref-pitch} is empty, @code{c'} is regarded as reference.
  "
   (define ref-pitch-steps
 (if (and (pair? ref-pitch) (car ref-pitch))
 (ly:pitch-steps (car ref-pitch))
 0))

   (call-with-values
(lambda ()
  (partition
   (lambda (note)
 (> (ly:pitch-steps (ly:music-property note 'pitch))
ref-pitch-steps))
   (event-chord-notes chord)))
(lambda (x y) (cons x y

autoSplitChord =
#(define-music-function (stem-dir staff-names pitch chord)
   ((ly:dir? 0) (pair? '("up" . "down")) (ly:pitch?) ly:music?)
   (_i "Split @var{chord} at optional @var{pitch}.  The default of @var{pitch} is
@code{#f}, which is interpreted by the called procedure
@code{make-autosplit-chord} as @code{c'}.

The splitted chords are distributed to named staves, relying on optional
@var{staff-names}.

The optional @var{stem-dir}, determines the direction of the stems and whether
the chords may be connected by a cross-staff stem.
The default results in unconnected chords.
If the @code{Span_stem_engraver} is consisted, the chords may be connected by a
cross-staff stem.")
   (let* ((skip (make-duration-of-length (ly:music-length chord)))
  (devided-pitches (make-autosplit-chord chord pitch))
  (upper-chord
   (if (pair? (car devided-pitches))
   (make-event-chord (car devided-pitches))
   (make-skip-music skip)))
  (lower-chord
   (if (pair? (cdr devided-pitches))
   (make-event-chord (cdr devided-pitches))
   (make-skip-music skip
 #{
   <<
 \context Staff = #(car staff-names)
 \context Voice {
   $(if (negative? stem-dir)
#{
  \once \override Stem.cross-staff = #cross-staff-connect
  \once \override Flag.style = #'no-flag
  <>\noBeam
#})
   $(if (not (zero? stem-dir))
#{ \once \override Stem.direction = #stem-dir #})
   #upper-chord
 }

 \context Staff = #(cdr staff-names)
 \context Voice {
   $(if (positive? stem-dir)
#{
  \once \override Stem.cross-staff = #cross-staff-connect
  \once \override Flag.style = #'no-flag
  <>\noBeam
#})
   $(if (not (zero? stem-dir))
#{ \once \override Stem.direction = 

Automatic cross-staff chords - testing help

2020-12-25 Thread Thomas Morley
Hi,

sometimes automatic cross-staff chords are requested here on the list.
After some thinking I come up with the code below.

Though, I suspect there are flaws in it, if used in real world codings.

I'd appreciate, if it would be tested in various situations.

Here the code:

\version "2.20.0"

#(define (make-autosplit-chord chord . ref-pitch)
  "Return a pair of lists, containing the pitches of @var{chord}, splitted at
a reference pitch.  The reference pitch is derived from @var{ref-pitch}.
If @var{ref-pitch} is empty, @code{c'} is regarded as reference.
  "
  (define ref-pitch-steps
(if (and (pair? ref-pitch) (car ref-pitch))
(ly:pitch-steps (car ref-pitch))
0))

  (call-with-values
(lambda ()
  (partition
(lambda (note)
  (> (ly:pitch-steps (ly:music-property note 'pitch))
 ref-pitch-steps))
(event-chord-notes chord)))
(lambda (x y) (cons x y

autoSplitChord =
#(define-music-function (stem-dir staff-names pitch chord)
  ((ly:dir? 0) (pair? '("up" . "down")) (ly:pitch?) ly:music?)
  (_i "Split @var{chord} at optional @var{pitch}.  The default of @var{pitch} is
@code{#f}, which is interpreted by the called procedure
@code{make-autosplit-chord} as @code{c'}.

The splitted chords are distributed to named staves, relying on optional
@var{staff-names}.

The optional @var{stem-dir}, determines the direction of the stems and whether
the chords may be connected by a cross-staff stem.
The default results in unconnected chords.
If the @code{Span_stem_engraver} is consisted, the chords may be connected by a
cross-staff stem.")
  (let* ((skip (make-duration-of-length (ly:music-length chord)))
 (devided-pitches (make-autosplit-chord chord pitch))
 (upper-chord
   (if (pair? (car devided-pitches))
   (make-event-chord (car devided-pitches))
   (make-skip-music skip)))
 (lower-chord
   (if (pair? (cdr devided-pitches))
   (make-event-chord (cdr devided-pitches))
   (make-skip-music skip
#{
  <<
\context Staff = #(car staff-names)
  \context Voice {
$(if (negative? stem-dir)
  #{
 \once \override Stem.cross-staff = #cross-staff-connect
 \once \override Flag.style = #'no-flag
 <>\noBeam
  #})
$(if (not (zero? stem-dir))
  #{ \once \override Stem.direction = #stem-dir #})
#upper-chord
  }

\context Staff = #(cdr staff-names)
  \context Voice {
$(if (positive? stem-dir)
  #{
 \once \override Stem.cross-staff = #cross-staff-connect
 \once \override Flag.style = #'no-flag
 <>\noBeam
  #})
$(if (not (zero? stem-dir))
  #{ \once \override Stem.direction = #stem-dir #})
#lower-chord
  }
  >>
#}))

%%
%% EXAMPLES
%%

\score {
  \new StaffGroup
\with { \consists #Span_stem_engraver }
<<
  \new Staff = "up" \with { instrumentName = "up" }
\new Voice = "foo" {
  \key g \major
  \clef "treble"
  <>^"possible stems"
  \autoSplitChord 4
  \autoSplitChord #DOWN 
  \autoSplitChord #UP 2
  \bar "||"

  <>^"various staves"

  %% While other staves are specified, the stems direction must be set
  %% as well.
  \autoSplitChord #CENTER #'("up" . "middle") 4
  \autoSplitChord #DOWN #'("middle" . "down") 
  %% If the chord is distributed in not descending order, \crossStaff
  %% needs to be set manually. See below in: \new Staff = "down" [...]
  \autoSplitChord #UP #'("down" . "middle") 2
  \bar "||"

  <>^"other split pitch"

  %% While other split pitches are specified, the stems direction and
  %% staff-names must be set as well.
  \autoSplitChord #CENTER #'("up" . "down") a'' 4
  \autoSplitChord #UP #'("up" . "down") e'' 
  \autoSplitChord #DOWN #'("up" . "down") g 
  \autoSplitChord #DOWN #'("up" . "down") e 
  \bar "||"
}

  \new Staff = "middle" \with { instrumentName = "middle" }
\new Voice = "bar"
  \crossStaff {
\key g \major
\clef "bass"
s1*3
  }

  \new Staff = "down" \with { instrumentName = "down" }
\new Voice = "buzz" {
  \key g \major
  \clef "bass"
  s1
  s2
  \clef "treble"
  \crossStaff
  s2
  s2
  \clef "bass"
  s2
}
>>
  \layout {
ragged-right = ##f
\override TextScript.staff-padding = 4
  }
}


\new PianoStaff
  \with { \consists #Span_stem_engraver }
  <<
\new Staff = "up"
  \new Voice = "foo" {