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: #<Context Voice () >, id="", uid=1, now=#<Mom -infinity>
> initialize: #<Context Voice=foo () >, id="foo", uid=2, now=#<Mom 1/4>
> initialize: #<Context Voice () >, id="", uid=3, now=#<Mom 1/4>
> finalize: #<Context Voice=foo () >, id="foo", uid=2, now=#<Mom 3/4>
> finalize: #<Context Voice () >, id="", uid=3, now=#<Mom 3/4>
> finalize: #<Context Voice () >, id="", uid=1, now=#<Mom 1>
> 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
>
>