Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
;; This file:
;;   http://anggtwu.net/elisp/2024-piano-roll-macros.el.html
;;   http://anggtwu.net/elisp/2024-piano-roll-macros.el
;;          (find-angg "elisp/2024-piano-roll-macros.el")
;; Author: Eduardo Ochs <eduardoochs@gmail.com>
;;
;; `eeks': like `eek', but the keys are "spaced (in time)".
;; `eeks' plays "notes" "spaced in time", like a pianola.
;; Compare:           (eek "RET Hello")
;;    with: (eeks 0.5 0.25 "RET Hello")
;;
;; «.macro»		(to "macro")
;; «.eeks»		(to "eeks")
;; «.test-eepitch»	(to "test-eepitch")


;; «macro»  (to ".macro")
;; Tests: (ee-let*-macro-eeks 0.25 0.5 "RET Hello" tevents)
;;        (ee-let*-macro-eeks 0.25 0.5 "RET Hello" ppushs)
;;        (ee-let*-macro-eeks 0.25 0.5 "RET Hello" prats)
;;        (ee-let*-macro-eeks 0.25 0.5 "RET Hello" (length tevents))
;;        (ee-let*-macro-eeks 0.25 0.5 "RET Hello" (find-eppp ppushs :end))
;;        (ee-let*-macro-eeks 0.25 0.5 "RET Hello" (find-eppp prats  :end))
;;        (ee-let*-macro-eeks 0.25 0.5 "RET Hello" (eval prats))
;;        (ee-let*-macro-eeks 0.25 0.5 nil (list dist nf8s f8s))
;;   See: (find-templates-intro "7. let* macros")
;;        (find-kla-intro "8. `cl-loop'")
;;  Skel: (find-let*-macro-links "eeks" "t0 dt str" "tevents pushs ppushs rats prats")
(defmacro ee-let*-macro-eeks (t0 dt str &rest code)
  (declare (indent 3))
  `(let* ((t0  ,t0)
          (dt  ,dt)
          (str ,str)
          (dist    (if (not str)
		       (- (save-excursion
			    (move-end-of-line 1)
			    (search-forward "*")
			    (line-number-at-pos))
			  (line-number-at-pos))))
	  (nf8s    (if dist (1- dist)))
	  (f8s     (if dist (cl-loop for i from 1 to nf8s concat " <f8>")))
          (tevents (ee-eek2 (or str f8s)))
          (pushs   (cl-loop for tevent in tevents
			    collect `(eek2 '(,tevent))))
          (rats    (cl-loop for push in pushs
			    collect `(run-at-time ,t0 nil 'eval ',push)
			    do (setq t0 (+ t0 dt))))
          (ppushs  (cons 'progn pushs))
	  (prats   (cons 'progn rats)))
     ,@code))


;; «eeks»  (to ".eeks")
;; Test: (eeks 1.5 0.5 "RET Hello")
(defun eeks (&optional t0 dt str)
  "Like `eek' and `eek2', but play the events spaced in time.
T0 is the time of the first event; DT is T1-T0, T2-T1, etc.
If STR is nil, play a series of <f8>s; this is meant to be used
in eepitch blocks.\n
See the tests before the definition of `ee-let*-macro-eeks'
to understand how this works."
  (ee-let*-macro-eeks
      (or t0 0.25)
      (or dt 0.125)
      str
    (eval prats)
    (list (length tevents) 'events)))


;; «test-eepitch»  (to ".test-eepitch")
'("This is a test block:
* (eepitch-shell)
* (eepitch-kill)
* (eepitch-shell)
** Type <f8> on the line below and wait:
* (eeks 0.5 0.5)
echo a
echo b
echo c
*
--")


;; Local Variables:
;; coding:  utf-8-unix
;; End: