Re: detecting the start and end of a polyphonic passage from scheme

2020-07-01 Thread Maurits Lamers
Hi all,

The way the staff is usually printed (through format and display) already gave 
me that idea, but it is good to see it confirmed.

Let me try to sketch my problem and perhaps you could help me find an answer on 
how to achieve it.
I am trying to find a way that I can serialize the voices and their content. 
The maximum size of the serialization block is a bar.
Within this bar, I need to be able to order voices from low to high or the 
other way around.
The polyphony in the serialization is indicated as either being full bar, 
partial bar or a combination of both.

My technique currently is to use (par) and (seq) to indicate parallel or 
sequential structures.
The example below would become something like this

(par (seq g1) (seq g'8 e'8 (par (seq a'8. g'16 f'8 e'16 f' g' f' e' d') (seq 
c'8 a d'8. c'16 b8 a16 b 

or by only describing the voices:

(par (seq "bottom") (seq "one" (par (seq "two") (seq "three")) )

The actual serialized output would then be (indicators between []) :

g'8 e'8 [start partial polyphony] a'8. g'16 f'8 e'16 f' g' f' e' d' 
[simultaneous voice start] c'8 a d'8. c'16 b8 a16 b [start full measure 
polyphony] g1

From the structure above it is doable to get to this serialization as the 
initialization order because the order of events will be

start of voice 1
start of voice 2
g'8 (voice 1)
g1 (voice 2)
e'8 (voice 1)
start of voice 3
start of voice 4

This allows me to "anchor" the partial bar polyphony to voice 1 as it is the 
last note.

I however realized that this approach is problematic in case the separation 
starts one eighth earlier, as it is no longer possible to find which voice is 
actually a partial bar 
polyphony or a whole bar.

Any kind of hierarchical info on those voices would have helped me make the 
separation properly. As it obviously doesn't work this way, I need a different 
approach.
I do see a solution which I saw before I took this approach, which is that I 
run rhythmically through the bar and "sort" the notes into the voices by 
keeping track of what sounds simultaneously. To be honest I have no clue how to 
do this. Moreover, there might be a better / easier way?

Thanks in advance,

cheers

Maurits

> Op 1 jul. 2020, om 11:34 heeft Aaron Hill  het 
> volgende geschreven:
> 
> On 2020-07-01 2:07 am, Maurits Lamers wrote:
>> Follow up question: is there a way to know the "parent" of the voices
>> as they are defined in the code?
>> In the following example, I would like to determine that voice "two"
>> splits off from voice "one" without relying on the context-id.
>> (ly:context-parent ctx) gives me the staff, not the "parent voice"...
>> [...]
> 
> If I am not mistaken, Voices do not form a hierarchy with each other.  The 
> parent context will always be some form of Staff.  Consider:
> 
> 
> \version "2.20.0"
> 
> \new Voice = outer { e'8 g' \new Voice = inner { a'2 } b'4 }
> 
> 
> LilyPond syntax might make it appear as if one Voice is "inside" another, but 
> that is an illusion.  In reality, the two voices are in parallel with each 
> other.  The inlining of the inner Voice here only serves to keep the outer 
> Voice alive.
> 
> Here is an alternate way to view the above:
> 
> 
> \version "2.20.0"
> 
> {
>  \new Voice = outer { e'8 g' }
>  <<
>\context Voice = outer { s2 }
>\new Voice = inner { a'2 }
>  >>
>  \context Voice = outer { b'4 }
> }
> 
> 
> Hopefully it is more clear that the two Voices are siblings, not parent-child.
> 
> 
> -- Aaron Hill
> 




Re: detecting the start and end of a polyphonic passage from scheme

2020-07-01 Thread Thomas Morley
Am Mi., 1. Juli 2020 um 11:08 Uhr schrieb Maurits Lamers
:
>
> Hi all,
>
> Follow up question: is there a way to know the "parent" of the voices as they 
> are defined in the code?
> In the following example, I would like to determine that voice "two" splits 
> off from voice "one" without relying on the context-id.
> (ly:context-parent ctx) gives me the staff, not the "parent voice"...
>
> \score {
>   \new Staff {
> \time 2/2
>
> <<
>   \new Voice = "one" {
> \relative c'' {
>   \voiceOne
>   g8 e
> }
> <<
>   \new Voice = "two" {
> \voiceOne
> \relative c'' { a8. g16 f8 e16 f g f e d }
>   }
>   \new Voice = "three" {
> \voiceTwo
> \relative c' { c8 a d8. c16 b8 a16 b }
>   }
> >>
>   }
>   \new Voice = bottom {
> \voiceTwo
> \relative c' { g1 }
>   }
> >>
>
>   }
> }
>
> Thanks in advance!
>

Hi Maurits,

I second Aaron, saying Voices are not parent of each other.
Below some other code I once made. Not exactly what you need, maybe
some addition to the fine code Aaron already provided, though.

#(define (my-engraver ctx)
  (let ((new-contexts '()))
 `(
   (listeners
(AnnounceNewContext
  .
  ,(lambda (engraver event)
(set! new-contexts (cons event new-contexts)
   (finalize
.
,(lambda (trans)
  (let ((ctx-type-id
  (map
(lambda (c)
  (let ((creator (ly:event-property c 'creator)))
(list
  (ly:event-property creator 'type)
  (ly:event-property creator 'id
(delete-duplicates (reverse new-contexts)
  (format #t
"\nInside this score ~a new contexts are created. Type and id are:\n~y"
(length ctx-type-id)
ctx-type-id)
  (set! ctx-type-id '()

  )))

#(define (single-context-parent-tree ctx)
  (if (and (ly:context? ctx) (ly:context? (ly:context-parent ctx)))
  (single-context-parent-tree (ly:context-parent ctx))
  (format #f "~a" ctx)))

printBottomContextParents =
\context Bottom
\applyContext
  #(lambda (a)
(let ((ls (drop-right
(string-split
  (single-context-parent-tree a)
  (car (string->list "(")))
1)))
(format #t "\n\nThe Context-parent-tree:")
(format #t
  "\n(Only contexts of type Global, Score, Staff and Voice are printed)")
(for-each
  (lambda (s)
(format #t "\n~a~a"
  (cond ((string-contains s "Score")
 (make-string 1 #\tab))
((string-contains s "Staff")
 (make-string 2 #\tab))
((string-contains s "Voice")
 (make-string 3 #\tab))
(else ""))
  (string-trim-both s (lambda (c)
(or (eqv? c #\>)
(eqv? c #\sp)
(eqv? c #\)))
  ls)))

\score {
  \new Staff {
\time 2/2


<<
  \new Voice = "one" {
\relative c'' {
  \voiceOne
  g8 e
}
<<
  \new Voice = "two" {
\voiceOne
\relative c'' { a8. g16 f8 e16 f g f e d }
  }
  \new Voice = "three" {
\voiceTwo
\relative c' { c8 a d8. c16 b8 a16 b }
  }
>>
  }
  \new Voice = bottom {
\voiceTwo

\relative c' { g1 }
  }
>>

  }

  \layout {
\context {
  \Score
  \consists \my-engraver
}
\printBottomContextParents
  }
}

Cheers,
  Harm



Re: detecting the start and end of a polyphonic passage from scheme

2020-07-01 Thread Aaron Hill

On 2020-07-01 2:07 am, Maurits Lamers wrote:

Follow up question: is there a way to know the "parent" of the voices
as they are defined in the code?
In the following example, I would like to determine that voice "two"
splits off from voice "one" without relying on the context-id.
(ly:context-parent ctx) gives me the staff, not the "parent voice"...

[...]


If I am not mistaken, Voices do not form a hierarchy with each other.  
The parent context will always be some form of Staff.  Consider:



\version "2.20.0"

\new Voice = outer { e'8 g' \new Voice = inner { a'2 } b'4 }


LilyPond syntax might make it appear as if one Voice is "inside" 
another, but that is an illusion.  In reality, the two voices are in 
parallel with each other.  The inlining of the inner Voice here only 
serves to keep the outer Voice alive.


Here is an alternate way to view the above:


\version "2.20.0"

{
  \new Voice = outer { e'8 g' }
  <<
\context Voice = outer { s2 }
\new Voice = inner { a'2 }
  >>
  \context Voice = outer { b'4 }
}


Hopefully it is more clear that the two Voices are siblings, not 
parent-child.



-- Aaron Hill



Re: detecting the start and end of a polyphonic passage from scheme

2020-07-01 Thread Maurits Lamers
Hi all,

Follow up question: is there a way to know the "parent" of the voices as they 
are defined in the code?
In the following example, I would like to determine that voice "two" splits off 
from voice "one" without relying on the context-id.
(ly:context-parent ctx) gives me the staff, not the "parent voice"...

\score {
  \new Staff {
\time 2/2

<<
  \new Voice = "one" {
\relative c'' {
  \voiceOne
  g8 e
}
<<
  \new Voice = "two" {
\voiceOne
\relative c'' { a8. g16 f8 e16 f g f e d }
  }
  \new Voice = "three" {
\voiceTwo
\relative c' { c8 a d8. c16 b8 a16 b }
  }
>>
  }
  \new Voice = bottom {
\voiceTwo
\relative c' { g1 }
  }
>>

  }
}

Thanks in advance!

cheers

Maurits



> Van: Aaron Hill 
> Onderwerp: Antw.: detecting the start and end of a polyphonic passage from 
> scheme
> Datum: 25 juni 2020 17:12:13 CEST
> Aan: lilypond-user@gnu.org
> 
> 
> On 2020-06-25 7:01 am, Maurits Lamers wrote:
>> Hi all,
>> I am trying to build a system based on the listener system which can
>> identify voices in a piece of music.
>> I use a listener to the Voice context to give me the note events.
>> In the following passage I can use (ly:context-id
>> (ly:translator-context engraver) to get the id, which is empty for c4,
>> "1" for the first voice, "2" for the second voice, and empty again for
>> d4 at the end.
>> time 4/4 \relative c' {  c4 << { c8 d e4 } \\ { c8 b c4 } >> d4 | }
>> However in the following passage the context-id cannot be used because
>> it is not set.
>> \relative c' {
>>  \new Voice {
>>c4
>><<
>>  \new Voice {
>>c8 d e4
>>  }
>>  \new Voice {
>>c8 b c4
>>  }
>>>>
>>d4
>>  }
>>}
>> I am currently using object properties to follow these voices by
>> setting a unique value for that voice context object, but that doesn't
>> help me
>> to detect properly the start and end of the polyphonic passage. The
>> main voice gets 1, the first nested voice will be 2, the second nested
>> voice will be 3.
>> For transcription purposes it would be very helpful to detect the
>> start and end of the polyphonic passage. Is this possible?
> 
> The initialize and finalize procedures of an engraver will run when the 
> context in which it is \consisted begins and ends.  Consider:
> 
> 
> \version "2.20.0"
> 
> #(define custom-uid
>  (let ((custom-uid-prop (make-object-property))
>(last-uid 0))
>(lambda (obj)
>  (or (custom-uid-prop obj)
>  (begin
>(set! last-uid (1+ last-uid))
>(set! (custom-uid-prop obj) last-uid)
>last-uid)
> 
> handle-init-and-final =
> #(lambda (context)
>  (make-engraver
>((initialize engraver)
>  (let* ((ctxt (ly:translator-context engraver))
> (id (ly:context-id ctxt))
> (uid (custom-uid ctxt))
> (now (ly:context-now ctxt)))
>(format #t "\ninitialize: ~s, id=~s, uid=~s, now=~s"
>  ctxt id uid now)))
>((finalize engraver)
>  (let* ((ctxt (ly:translator-context engraver))
> (id (ly:context-id ctxt))
> (uid (custom-uid ctxt))
> (now (ly:context-now ctxt)))
>(format #t "\nfinalize: ~s, id=~s, uid=~s, now=~s"
>  ctxt id uid now)
> 
> \layout { \context { \Voice \consists \handle-init-and-final } }
> 
> { \relative c' { \new Voice { c4
>  << \new Voice = foo { \voiceOne c8 d e4 }
> \new Voice { \voiceTwo c8 b c4 } >> d4 } } }
> 
> 
> 
> . . .
> Parsing...
> Interpreting music...
> initialize: #, id="", uid=1, now=#
> initialize: #, id="foo", uid=2, now=#
> initialize: #, id="", uid=3, now=#
> finalize: #, id="foo", uid=2, now=#
> finalize: #, id="", uid=3, now=#
> finalize: #, id="", uid=1, now=#
> Preprocessing graphical objects...
> . . .
> 
> 
> NOTE: I am using Scheme object properties to attach a custom unique 
> identifier to the contexts as they are seen, so it is possible to discern 
> which context is which even when they are not named.
> 
> 
> -- Aaron Hill
> 
> 
> 
> 
> ___
> lilypond-user mailing list
> lilypond-user@gnu.org
> https://lists.gnu.org/mailman/listinfo/lilypond-user



Re: detecting the start and end of a polyphonic passage from scheme

2020-06-25 Thread Maurits Lamers
Hi, 

Great solution, thanks a lot!

cheers

Maurits


> On 2020-06-25 7:01 am, Maurits Lamers wrote:
> Hi all,
> 
> I am trying to build a system based on the listener system which can
> identify voices in a piece of music.
> I use a listener to the Voice context to give me the note events.
> 
> In the following passage I can use (ly:context-id
> (ly:translator-context engraver) to get the id, which is empty for c4,
> "1" for the first voice, "2" for the second voice, and empty again for
> d4 at the end.
> 
> time 4/4 \relative c' {  c4 << { c8 d e4 } \\ { c8 b c4 } >> d4 | }
> 
> 
> However in the following passage the context-id cannot be used because
> it is not set.
> 
> \relative c' {
>   \new Voice {
> c4
> <<
>   \new Voice {
> c8 d e4
>   }
>   \new Voice {
> c8 b c4
>   }
> >>
> d4
>   }
> }
> 
> I am currently using object properties to follow these voices by
> setting a unique value for that voice context object, but that doesn't
> help me
> to detect properly the start and end of the polyphonic passage. The
> main voice gets 1, the first nested voice will be 2, the second nested
> voice will be 3.
> For transcription purposes it would be very helpful to detect the
> start and end of the polyphonic passage. Is this possible?
> The initialize and finalize procedures of an engraver will run when the 
> context in which it is \consisted begins and ends. Consider:
> 
> \version "2.20.0"
> 
> #(define custom-uid
>   (let ((custom-uid-prop (make-object-property))
> (last-uid 0))
> (lambda (obj)
>   (or (custom-uid-prop obj)
>   (begin
> (set! last-uid (1+ last-uid))
> (set! (custom-uid-prop obj) last-uid)
> last-uid)
> 
> handle-init-and-final =
> #(lambda (context)
>   (make-engraver
> ((initialize engraver)
>   (let* ((ctxt (ly:translator-context engraver))
>  (id (ly:context-id ctxt))
>  (uid (custom-uid ctxt))
>  (now (ly:context-now ctxt)))
> (format #t "\ninitialize: ~s, id=~s, uid=~s, now=~s"
>   ctxt id uid now)))
> ((finalize engraver)
>   (let* ((ctxt (ly:translator-context engraver))
>  (id (ly:context-id ctxt))
>  (uid (custom-uid ctxt))
>  (now (ly:context-now ctxt)))
> (format #t "\nfinalize: ~s, id=~s, uid=~s, now=~s"
>   ctxt id uid now)
> 
> \layout { \context { \Voice \consists \handle-init-and-final } }
> 
> { \relative c' { \new Voice { c4
>   << \new Voice = foo { \voiceOne c8 d e4 }
>  \new Voice { \voiceTwo c8 b c4 } >> d4 } } }
> 
> 
> 
> . . .
> Parsing...
> Interpreting music...
> initialize: #, id="", uid=1, now=#
> initialize: #, id="foo", uid=2, now=#
> initialize: #, id="", uid=3, now=#
> finalize: #, id="foo", uid=2, now=#
> finalize: #, id="", uid=3, now=#
> finalize: #, id="", uid=1, now=#
> Preprocessing graphical objects...
> . . .
> 
> 
> NOTE: I am using Scheme object properties to attach a custom unique 
> identifier to the contexts as they are seen, so it is possible to discern 
> which context is which even when they are not named.
> 
> -- Aaron Hill
> 
> 



Re: detecting the start and end of a polyphonic passage from scheme

2020-06-25 Thread Aaron Hill

On 2020-06-25 7:01 am, Maurits Lamers wrote:

Hi all,

I am trying to build a system based on the listener system which can
identify voices in a piece of music.
I use a listener to the Voice context to give me the note events.

In the following passage I can use (ly:context-id
(ly:translator-context engraver) to get the id, which is empty for c4,
"1" for the first voice, "2" for the second voice, and empty again for
d4 at the end.

time 4/4 \relative c' {  c4 << { c8 d e4 } \\ { c8 b c4 } >> d4 | }


However in the following passage the context-id cannot be used because
it is not set.

\relative c' {
  \new Voice {
c4
<<
  \new Voice {
c8 d e4
  }
  \new Voice {
c8 b c4
  }
>>
d4
  }
}

I am currently using object properties to follow these voices by
setting a unique value for that voice context object, but that doesn't
help me
to detect properly the start and end of the polyphonic passage. The
main voice gets 1, the first nested voice will be 2, the second nested
voice will be 3.
For transcription purposes it would be very helpful to detect the
start and end of the polyphonic passage. Is this possible?


The initialize and finalize procedures of an engraver will run when the 
context in which it is \consisted begins and ends.  Consider:



\version "2.20.0"

#(define custom-uid
  (let ((custom-uid-prop (make-object-property))
(last-uid 0))
(lambda (obj)
  (or (custom-uid-prop obj)
  (begin
(set! last-uid (1+ last-uid))
(set! (custom-uid-prop obj) last-uid)
last-uid)

handle-init-and-final =
#(lambda (context)
  (make-engraver
((initialize engraver)
  (let* ((ctxt (ly:translator-context engraver))
 (id (ly:context-id ctxt))
 (uid (custom-uid ctxt))
 (now (ly:context-now ctxt)))
(format #t "\ninitialize: ~s, id=~s, uid=~s, now=~s"
  ctxt id uid now)))
((finalize engraver)
  (let* ((ctxt (ly:translator-context engraver))
 (id (ly:context-id ctxt))
 (uid (custom-uid ctxt))
 (now (ly:context-now ctxt)))
(format #t "\nfinalize: ~s, id=~s, uid=~s, now=~s"
  ctxt id uid now)

\layout { \context { \Voice \consists \handle-init-and-final } }

{ \relative c' { \new Voice { c4
  << \new Voice = foo { \voiceOne c8 d e4 }
 \new Voice { \voiceTwo c8 b c4 } >> d4 } } }



. . .
Parsing...
Interpreting music...
initialize: #, id="", uid=1, now=#
initialize: #, id="foo", uid=2, now=#
initialize: #, id="", uid=3, now=#
finalize: #, id="foo", uid=2, now=#
finalize: #, id="", uid=3, now=#
finalize: #, id="", uid=1, now=#
Preprocessing graphical objects...
. . .


NOTE: I am using Scheme object properties to attach a custom unique 
identifier to the contexts as they are seen, so it is possible to 
discern which context is which even when they are not named.



-- Aaron Hill