David Kastrup <d...@gnu.org> writes: > Dan Eble <d...@faithful.be> writes: > >> On Jun 12, 2021, at 18:48, David Kastrup <d...@gnu.org> wrote: >>> >>> So how robust (or not) would be the following approach? Make it >>> possible to write in the timing track something like >>> >>> \rit 2/3 { \skip 1*2 } >>> >>> with the effect that some run-always translator keeps adjusting >>> tempoWholesPerMinute during the \skip (in proportion to where the time >>> is) until it is at 2/3 the speed at the end when it gets reset. >> >> As a user, I think I would rather specify the tempo at the endpoint. > > That requires you to remember the tempo at the startpoint if you go for > a particular kind of slowdown. > >> Is there any hope of handling tempo adjustments like dynamic >> adjustments? >> >> \mf … \< … \f >> >> \tempo 4 = 90 … \startLinearTempoChange … \tempo 4 = 60 > > Of course the question is what "linear" means with regard to a tempo > change. MIDI files measure durations in terms of common-time (the basic > MIDI clock is 1/24th of a quarter note), so you actually are reduced to > writing tempo change events (which take the form of specifying µs/♩) > between note events. They don't clog up the raw MIDI signal lines > (those running at 31250bps) since they are "meta events" and converted > into timing for the "real" events by whatever player/sequencer > translates the MIDI file into a timed sequence of commands. > >> I don't remember very clearly how the dynamic performance looks ahead >> to manage as it does, but I think it might be that the MIDI generation >> occurs in a second pass, and a velocity value isn't actually needed >> until then. It might be possible to record a piecewise function for >> the tempo during normal iteration, and then use that to stretch or >> compress MIDI time as the raw MIDI events are being generated. > > We are not outputting a timed sequence of events but MIDI files, so we > just can intersperse tempo events: the actual timing in the MIDI file is > being expressed in terms of common-time quarternotes and is unimpressed > by rit/acc. > > Of course that also begs the question of how often to output a tempo > change: it's conceivable that you run an arranger for accompanying music > that takes its timing from the generated MIDI file, and when it > accompanies long notes in a ritardando, the slowdown of the > accompaniment should likely occur more gradually than one tempo event > per long note. > >> I would love to have this feature. I'm glad you're considering it. > > More thinking about what it would entail than considering it.
I actually don't think that a lot more than the following is needed (by the way: it is patently ridiculous that it requires \articulate for getting tomh1:32 rendered as more than one note).
tempoChange = #(define-music-function (interval endscale thenscale music) "Make a gradual tempo change over @var{music}, essentially changing speed after every duration of @var{interval}, approaching a factor of speed of @var{endscale} compared to the start. Afterwards, tempo is switched to @var{endscale} of the original speed (default 1). If @var{endscale} is 0, the speed reached at the end is just maintained and can be overriden with an explicit @samp{\\tempo} command if required." (ly:duration? scale? (scale? 1) ly:music?) (define (scaletempo oldscale newscale) (make-apply-context (lambda (ctx) (set! (ly:context-property ctx 'tempoWholesPerMinute) (ly:moment-mul (ly:context-property ctx 'tempoWholesPerMinute) (ly:make-moment (/ newscale oldscale))))))) (let* ((muslen (ly:moment-main (ly:music-length music))) (intlen (ly:moment-main (ly:duration-length interval))) (steps (/ muslen intlen)) (endfactor (scale->factor endscale)) (thenfactor (scale->factor thenscale))) (make-simultaneous-music (list music (context-spec-music (make-sequential-music (let loop ((rsteplst (iota (1+ steps) endfactor (/ (- 1 endfactor) steps))) (res (if (positive? thenfactor) (list (scaletempo endfactor thenfactor)) (list)))) (if (null? (cdr rsteplst)) res (loop (cdr rsteplst) (cons* (scaletempo (cadr rsteplst) (car rsteplst)) (make-skip-music (ly:make-duration 0 0 intlen)) res))))) 'Score))))) \include "articulate.ly" \score { \articulate \drums { \tempo 4 = 80 tomh1:32 \tempoChange 4 ##e0.6 { tomh1:32 } tomh1:32 \tempoChange 2 ##e0.6 { tomh1:32 } tomh1:32 \tempoChange 32 6/5 ##e0.6 { tomh1:32 } tomh1:32 \tempoChange 32 #(/ #e0.6) 0 { tomh1:32 } tomh1:32 } \midi {} }
-- David Kastrup