Re: Scheme performers/translators
Han-Wen Nienhuys writes: > On Thu, Sep 30, 2021 at 12:24 AM David Kastrup wrote: >> >> Well, this is not as much supporting the MIDI layer as it is >> employing the translator level for messing with music during >> iteration. It's sort of annoying that it doesn't work by default. > > It doesn't work by default because we never bothered to invest time in > improving it. You are changing the topic. It's sort of annoying that employing the translator level for messing with music during iteration doesn't work by default since all that is required for that is not deleting the already instantiated translator from the respective lists. > It's not obvious to me that a principled approach to MIDI rendering > would use a broadcast/acknowledge type architecture like the > typography part does. Not relevant at all to this patch. -- David Kastrup
Re: Scheme performers/translators
On Thu, Sep 30, 2021 at 12:24 AM David Kastrup wrote: > > Aaron Hill writes: > > > On 2021-09-29 12:39 pm, David Kastrup wrote: > >> The question is whether we should do something like this as default, > >> possibly conditioned on whether any acknowledgers are present? Because > >> even if we cannot react to Midi data structures (since they are not > >> Scheme-accessible for now), sometimes a translator may be enough to do > >> the trick. > > > > You say "for now" above, so is allowing Scheme to interact directly > > with the MIDI stream something that is planned? > > I have no idea what you call "planned". It is a deficiency that one > cannot use LilyPond in anything but a hardwired manner for creating > Midi. That does not mean that I know this to be in anybody's personal > work queue. At the current point of time, the Midi data structures are > not even in the Scheme memory management. I think most of them just > stick around without ever getting deleted. Audio elements get deleted in Performance::~Performance, and I'd be surprised if the MIDI stuff gets leaked. MIDI didn't show up the memory leak hunt Jonas and I did about 9 months ago. File a bug if you can repro a leak? > > Between what you have just shown and the work that already occurs in > > articulate.ly, it seems a lot of practical manipulation is possible > > without going down to the MIDI layer. So, your little patch to enable > > wider use of Scheme translators seems quite useful. At the very > > least, the more folks build on this and start playing around with the > > music, the more we would understand what a potential full Scheme > > performer support would entail. > > Well, this is not as much supporting the MIDI layer as it is employing > the translator level for messing with music during iteration. It's sort > of annoying that it doesn't work by default. It doesn't work by default because we never bothered to invest time in improving it. It's not obvious to me that a principled approach to MIDI rendering would use a broadcast/acknowledge type architecture like the typography part does. -- Han-Wen Nienhuys - hanw...@gmail.com - http://www.xs4all.nl/~hanwen
Re: Scheme performers/translators
Aaron Hill writes: > On 2021-09-29 12:39 pm, David Kastrup wrote: >> The question is whether we should do something like this as default, >> possibly conditioned on whether any acknowledgers are present? Because >> even if we cannot react to Midi data structures (since they are not >> Scheme-accessible for now), sometimes a translator may be enough to do >> the trick. > > You say "for now" above, so is allowing Scheme to interact directly > with the MIDI stream something that is planned? I have no idea what you call "planned". It is a deficiency that one cannot use LilyPond in anything but a hardwired manner for creating Midi. That does not mean that I know this to be in anybody's personal work queue. At the current point of time, the Midi data structures are not even in the Scheme memory management. I think most of them just stick around without ever getting deleted. > Between what you have just shown and the work that already occurs in > articulate.ly, it seems a lot of practical manipulation is possible > without going down to the MIDI layer. So, your little patch to enable > wider use of Scheme translators seems quite useful. At the very > least, the more folks build on this and start playing around with the > music, the more we would understand what a potential full Scheme > performer support would entail. Well, this is not as much supporting the MIDI layer as it is employing the translator level for messing with music during iteration. It's sort of annoying that it doesn't work by default. -- David Kastrup
Re: Scheme performers/translators
On 2021-09-29 12:39 pm, David Kastrup wrote: The question is whether we should do something like this as default, possibly conditioned on whether any acknowledgers are present? Because even if we cannot react to Midi data structures (since they are not Scheme-accessible for now), sometimes a translator may be enough to do the trick. You say "for now" above, so is allowing Scheme to interact directly with the MIDI stream something that is planned? Between what you have just shown and the work that already occurs in articulate.ly, it seems a lot of practical manipulation is possible without going down to the MIDI layer. So, your little patch to enable wider use of Scheme translators seems quite useful. At the very least, the more folks build on this and start playing around with the music, the more we would understand what a potential full Scheme performer support would entail. -- Aaron Hill
Re: Scheme performers/translators
David Kastrup writes: > So I tried the following > > Stress_performer = > #(define-scheme-function (strong weak) (index? index?) >(lambda (ctx) > (define fired #f) > (define (emit weight) >(ly:broadcast (ly:event-source ctx) >(ly:make-stream-event > (ly:make-event-class 'articulation-event) > `((articulation-type . "accent") > (midi-extra-velocity . ,weight) > (make-engraver > ((stop-translation-timestep c) (set! fired #f)) >; TODO: don't go against syncopation: if there has been an >; explicit accent less than a beat ago, don't do anything > (listeners ((note-event performer event) > (if (not fired) > (let ((mp (ly:context-property ctx 'measurePosition)) > (tf (ly:context-property ctx 'timeSignatureFraction > '(4 . 4))) > (bmm (ly:context-property ctx 'baseMoment)) > (bm (if (ly:moment? bmm) > (ly:moment-main bmm) > (/ (cdr tf > (bs (ly:context-property ctx 'beatStructure))) > (set! fired #t) > (and (zero? (ly:moment-grace mp)) >(zero? (ly:moment-main (ly:moment-mod mp bm))) >(let loop ((mp (ly:moment-main mp)) (bs bs) (w > strong)) > (cond ((zero? mp) (emit w)) >((positive? mp) > (if (pair? bs) > (loop (- mp (* bm (car bs))) (cdr bs) > weak) > (loop (- mp bm) bs weak) > > > and it did nothing when used via > > \midi { \context { \DrumVoice \consists \Stress_performer 20 10 } } > > when the intent was that there should be additional midi velocity on the > start of the bar and then on each beat. Now the code, not having run, > may very well be defective still. But the point is that it doesn't even > get called because a Scheme_engraver is an engraver and engravers are > not getting called in \midi. > > This actually does nothing that couldn't be done in general by any > translator: it doesn't even require to specifically be an engraver or > performer. > > I am somewhat loth to just copy scheme-engraver.{cc,hh} to > scheme-performer.{cc,hh}, throw out everything Engraver-specific > (basically acknowledgers and possibly the associated processing phases) > and get something pretty much the same for now. > > Does anybody have a better proposal? Ok, I now fixed the performer for basic use: Stress_performer = #(define-scheme-function (strong weak) (index? index?) (lambda (ctx) (define fired #f) (define (emit weight) (ly:broadcast (ly:context-event-source ctx) (ly:make-stream-event (ly:make-event-class 'articulation-event) `((articulation-type . "accent") (midi-extra-velocity . ,weight) (make-engraver ((stop-translation-timestep c) (set! fired #f)) ; TODO: don't go against syncopation: if there has been an ; explicit accent less than a beat ago, don't do anything (listeners ((note-event performer event) (if (not fired) (let* ((mp (ly:context-property ctx 'measurePosition)) (mpm (ly:moment-main mp)) (tf (ly:context-property ctx 'timeSignatureFraction '(4 . 4))) (bmm (ly:context-property ctx 'baseMoment)) (bm (if (ly:moment? bmm) (ly:moment-main bmm) (/ (cdr tf (bs (ly:context-property ctx 'beatStructure))) (set! fired #t) (and (zero? (ly:moment-grace mp)) (integer? (/ mpm bm)) (let loop ((mp mpm) (bs bs) (w strong)) (cond ((zero? mp) (emit w)) ((positive? mp) (if (pair? bs) (loop (- mp (* bm (car bs))) (cdr bs) weak) (loop (- mp bm) bs weak) And it works as \midi { \context { \DrumVoice \consists \Stress_performer 20 10 } } as long as I apply the following simplistic patch: diff --git a/lily/translator-group.cc b/lily/translator-group.cc index 07ba2f0395..4447747b73 100644 --- a/lily/translator-group.cc +++ b/lily/translator-group.cc @@ -156,7 +156,9 @@ Translator_group::create_child_translator (SCM sev) if (dynamic_cast (g))
Scheme performers/translators
So I tried the following Stress_performer = #(define-scheme-function (strong weak) (index? index?) (lambda (ctx) (define fired #f) (define (emit weight) (ly:broadcast (ly:event-source ctx) (ly:make-stream-event (ly:make-event-class 'articulation-event) `((articulation-type . "accent") (midi-extra-velocity . ,weight) (make-engraver ((stop-translation-timestep c) (set! fired #f)) ; TODO: don't go against syncopation: if there has been an ; explicit accent less than a beat ago, don't do anything (listeners ((note-event performer event) (if (not fired) (let ((mp (ly:context-property ctx 'measurePosition)) (tf (ly:context-property ctx 'timeSignatureFraction '(4 . 4))) (bmm (ly:context-property ctx 'baseMoment)) (bm (if (ly:moment? bmm) (ly:moment-main bmm) (/ (cdr tf (bs (ly:context-property ctx 'beatStructure))) (set! fired #t) (and (zero? (ly:moment-grace mp)) (zero? (ly:moment-main (ly:moment-mod mp bm))) (let loop ((mp (ly:moment-main mp)) (bs bs) (w strong)) (cond ((zero? mp) (emit w)) ((positive? mp) (if (pair? bs) (loop (- mp (* bm (car bs))) (cdr bs) weak) (loop (- mp bm) bs weak) and it did nothing when used via \midi { \context { \DrumVoice \consists \Stress_performer 20 10 } } when the intent was that there should be additional midi velocity on the start of the bar and then on each beat. Now the code, not having run, may very well be defective still. But the point is that it doesn't even get called because a Scheme_engraver is an engraver and engravers are not getting called in \midi. This actually does nothing that couldn't be done in general by any translator: it doesn't even require to specifically be an engraver or performer. I am somewhat loth to just copy scheme-engraver.{cc,hh} to scheme-performer.{cc,hh}, throw out everything Engraver-specific (basically acknowledgers and possibly the associated processing phases) and get something pretty much the same for now. Does anybody have a better proposal? -- David Kastrup