;;;; GNU LilyPond scheme file ;;;; ;;;; Copyright (C) 2012 Johannes Rohrer ;;;; ;;;; This program is free software: you can redistribute it and/or ;;;; modify it under the terms of the GNU General Public License as ;;;; published by the Free Software Foundation, either version 3 of ;;;; the License, or (at your option) any later version. ;;;; ;;;; This program is distributed in the hope that it will be useful, ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;;; General Public License for more details. ;;;; ;;;; You should have received a copy of the GNU General Public License ;;;; along with this program. If not, see ;;;; . ;; Provide music functions that scale music event durations to create ;; a swing feeling. This influences both notation spacing and MIDI ;; output. ;; ;; \applySwing swingDiv weightList music ;; ;; \applySwingWithOffset swingDiv offset weightList music ;; ;; \tripletFeel swingDiv music ;; ;; See the function docstrings and usage examples below for more ;; information. ;; Originally inspired by the discussion on LilyPond issue #687 ;; , ;; especially the contributions by "chicagogrooves" and "Arvid". ;;; Usage examples: ;; %% swung eigth or sixteenth notes ;; ;; \tripletFeel 8 { c8 c } ;; %% result: { c8*4/3 c8*2/3 }, ;; %% corresponding to \times 2/3 { c4 c8 } ;; ;; \tripletFeel 16 { c16 c } ;; %% result: { c16*4/3 c16*2/3 }, ;; %% corresponding to \times 2/3 { c8 c16 } ;; ;; ;; %% samba swing ;; ;; \applySwing 16 #'(3 2 2 3) { c16 c c c } ;; %% result corresponding to \times 4/5 { c16. c16 c c16. } ;; ;; \applySwing 16 #'(4 3 3 4) { c16 c c c } % smoother ;; %% result corresponding to \times 8/7 { c16 c32. c c16 } ;;; Known limitations: ;; * \repeat constructs in music (even \repeat unfold) are not taken ;; into consideration when determining note timing. This will lead ;; to problems unless the durations of all repeated parts are ;; integer multiples of the swing cycle duration. ;; ;; * These functions are oblivious to time signatures and measures. ;; ;; That is why offsets need to be supplied by the user if music ;; starts off-beat. ;; ;; * Grace notes are ignored and simply left unaffected. ;; ;; * Treatment of notes shorter than swingDiv is ad-hoc and may not be ;; what you want. ;; ;; In some detail: \applySwing operates by shifting the boundary ;; between two events if it falls on an off-beat multiple of ;; swingDiv. Assuming forward shift (backward shift works ;; analogously), this is done by first lengthening the earlier ;; event, then shortening the following event(s) by the same amount. ;; ;; Notes shorter than swingDiv never trigger the first step, hence ;; all notes in the following examples remain straight: ;; ;; \tripletFeel 8 { c16 c c c } ;; \tripletFeel 8 { c16 c c8 } ;; ;; However, if they appear after a note that has already been ;; lengthened, they will be shortened in the second step. Therefore, ;; ;; \tripletFeel 8 { c8 c16 c } ;; ;; will result in timing corresponding to \times 2/3 { c4 c16 c }. ;;; Helper functions (define (rational-list? lst) (and (list? lst) (fold (lambda (x y) (and x y)) #t (map rational? lst)))) (define (integers-from-1-to n) (if (< n 1) '() (append (integers-from-1-to (1- n)) (list n)))) (define (moment-abs mom) (if (ly:moment