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