;; int -> bool (define midi-division-is-metrical? (lambda (division) (not (fxbit-set? division 15)))) ;; int -> bool (define midi-division-is-time-code? (lambda (division) (fxbit-set? division 15))) ;; int -> int (define midi-division-time-code-format (lambda (division) (if (not (midi-division-is-time-code? division)) (error "midi-division-time-code-format" "division is not time code based" division) #f) (- (expt 2 8) (fxarithmetic-shift-right division 8)))) ;; int -> int (define midi-division-ticks-per-frame (lambda (division) (if (not (midi-division-is-time-code? division)) (error "midi-division-ticks-per-frame" "Division is not time code based" division) #f) (fxand (- (expt 2 8) 1) division))) ;; int -> int -> int -> double (define midi-delta-ticks-to-seconds (lambda (ticks division tempo) (if (midi-division-is-metrical? division) (let ((quarter-notes (/ ticks division)) (seconds-per-quarter-note (/ 60 tempo))) (* quarter-notes seconds-per-quarter-note)) (let ((smpte-format (midi-division-time-code-format division)) (smpte-resolution (midi-division-ticks-per-frame division))) (/ ticks (* smpte-format smpte-resolution)))))) ;; double -> int -> int -> int (define midi-seconds-to-delta-ticks (lambda (seconds division tempo) (if (midi-division-is-metrical? division) (exact (round (/ (* division seconds) (/ 60.0 tempo)))) (let ((smpte-format (midi-division-time-code-format division)) (smpte-resolution (midi-division-ticks-per-frame division))) (exact (round (* seconds smpte-format smpte-resolution))))))) ;; double -> int -> int (define midi-pulses-to-delta-ticks (lambda (pulses division) (if (midi-division-is-metrical? division) (exact (round (* division pulses))) (error "midi-pulses-to-delta-ticks" "division is not metrical")))) ;; double -> int (define midi-qpm-to-upq (lambda (qpm) (exact (round (* (/ 60 qpm) 1000000))))) ;; double -> int (define midi-upq-to-qpm (lambda (tempo) (exact (round (* (/ 60.0 tempo) 1000000.0)))))