[EMAIL PROTECTED] writes: > Hello, I have used Lilypond just last week to create a few musical > scores (pop music with a chordline, melody line, and lyrics). > > Anyway I have some comments regarding usage, mainly the problems I > encountered. I can possibly fix them given some encouragement...mainly > I want to know if anything has been done to address these problems? > > (I'm using LilyPond 2.2 on both RH9 Linux and Windows XP) > > > -> I use | a lot to separate measures, and am always running up > against the "| not at a measure boundary" warning...obviously I am > constantly having notes/measures between bars that don't add up to the > time signature. This was a major slowdown and pain to deal with...I'd > like to figure out some way to fix this problem. > > One notion I have is an addition to LilyPond's emacs mode that > operates similar to Emacs's column-mode (which automatically displays > the cursor's column number on the modeline). This addition would > simply indicate on the modeline just what beat the cursor is on...or > rather how many beats lie between the cursor and the previous | or {. > > With that in place, I could prevent those measure boundary warnings, > b/c I would know how 'full' each measure was when I type it in. > > Has anyone attacked this problem? I could be convinced to work on a > patch if no one else has... <snip>
Since no one else has attacked this problem, I figured I'd take a whack at it. My results are appended to this message. Going to try it for a few days & see how well it works. To use it, I tweaked my .emacs file as follows: (load-library "lilypond-init.el") ; already there (load "/usr0/svoboda/sw/elisp/what-beat.el") ; this file (add-hook 'LilyPond-mode-hook (lambda () (local-set-key "\C-cb" 'what-beat))) Hence 'C-c b' displays the current beat in the minibuffer; displayed as a ratio. i.e. if it shows 3/8, it means there are the equivalent of 3 eighth notes between the point and the last measure indicator (|). Comments? Buggestions? -- David Svoboda [EMAIL PROTECTED] Senior Research Programmer http://www.cs.cmu.edu/~svoboda Language Technologies Institute Practice Kind Randomness and Carnegie Mellon University Beautiful Acts of Nonsense ----- (setq pitch-regex "\\([a-z]+[,']*\\(=[,']\\)?\\)\\|<[^>]*>") (setq duration-regex "\\([ \t]*\\(128\\|6?4\\|3?2\\|16?\\|8\\)\\([.]*\\)\\([ \t]*[*][ \t]*\\([0-9]+\\)\\(/\\([1-9][0-9]*\\)\\)?\\)?\\)") (defun extract-match (string match-num) (if (null (match-beginning match-num)) nil (substring string (match-beginning match-num) (match-end match-num)))) (defun add-fractions (f1 f2) "Adds two fractions, both are (numerator denominator)" (set 'result (list (+ (* (car f1) (cadr f2)) (* (car f2) (cadr f1))) (* (cadr f1) (cadr f2)))) (set 'result (reduce-fraction result 2)) (set 'result (reduce-fraction result 3)) (set 'result (reduce-fraction result 5)) (set 'result (reduce-fraction result 7)) ) (defun reduce-fraction (f divisor) "Eliminates divisor from fraction if present" (while (and (= 0 (% (car result) divisor)) (= 0 (% (cadr result) divisor)) (< 1 (cadr result)) (< 0 (car result))) (set 'result (list (/ (car result) divisor) (/ (cadr result) divisor)))) result ) (defun parse-duration (duration) "Returns a duration string parsed as '(numerator denominator)" (string-match duration-regex duration) (let ((result (list 1 (string-to-int (extract-match duration 2)))) (dots (extract-match duration 3)) (numerator (or(extract-match duration 5) "1")) (denominator (or (extract-match duration 7) "1"))) (if (and (not (null dots)) (< 0 (string-width dots))) (dotimes (dummy (string-width dots)) (set 'result (list (1+ (* 2 (car result))) (* 2 (cadr result)))))) (list (* (string-to-int numerator) (car result)) (* (string-to-int denominator) (cadr result))) )) (defun walk-note-duration () "Returns duration of next note, moving point past note. If point is not before a note, returns nil If next note has no duration, returns t" (if (not (looking-at pitch-regex)) nil (progn (goto-char (match-end 0)) (if (not (looking-at duration-regex)) t (progn (goto-char (match-end 0)) (parse-duration(match-string 0))))))) (defun get-beat () (save-excursion (save-restriction (let* ((end (point)) (measure-start (or(re-search-backward "\|" 0 t) 0)) (last-dur (or(re-search-backward duration-regex 0 t) 0)) (duration (parse-duration(match-string 0))) (result '(0 1))) ; 0 in fraction form (if (= measure-start 0) (error "No | before point") (progn (goto-char (1+ measure-start)) (skip-chars-forward " \t\n") (while (< (point) end) (set 'new-duration (walk-note-duration)) (if (null new-duration) (if (looking-at "\\\\times[ \t]*\\([1-9]*\\)/\\([1-9]*\\)[ \t\n]*{") (let ((numerator (string-to-int(match-string 1))) (denominator (string-to-int(match-string 2)))) (goto-char (match-end 0)) (skip-chars-forward " \t\n") (while (and (not (looking-at "}")) (< (point) end)) (set 'new-duration (walk-note-duration)) (if (null new-duration) (if (looking-at "\\\\[a-z]*[ \t]*[a-z]*") (goto-char (match-end 0)) (error "Unknown text: %S %s" result(buffer-substring (point) end)))) (if (not (eq new-duration t)) (set 'duration new-duration)) (set 'result (add-fractions result (list (* numerator (car duration)) (* denominator (cadr duration))))) (skip-chars-forward " \t\n")) (if (< (point) end) (forward-char 1))) ; skip } (if (looking-at "\\\\[a-z]*[ \t]*[a-z]*") (goto-char (match-end 0)) (error "Unknown text: %S %s" result(buffer-substring (point) end)))) (if (not (eq new-duration t)) (set 'duration new-duration)) (set 'result (add-fractions result duration))) (skip-chars-forward " \t\n")) result )))))) (defun what-beat () "Returns how much of a measure lies between last measaure '|' and point. Recognizes chords, triples, and /clef & other context words." (interactive) (let ((beat (get-beat))) (message "%d/%d" (car beat) (cadr beat))) ) _______________________________________________ lilypond-user mailing list [EMAIL PROTECTED] http://lists.gnu.org/mailman/listinfo/lilypond-user