view implementations/gsharp/gsharp-import.lisp @ 59:08468c3d5801

gsharp amuse implementation darcs-hash:20070622062520-df18d-6c619e5668475044d209a1d987c24695ac065679.gz
author csr21 <csr21@cantab.net>
date Fri, 22 Jun 2007 07:25:20 +0100
parents
children 8cc40d2b12fd
line wrap: on
line source
(in-package "AMUSE-GSHARP")

(defun last-bar-p (bar)
  ;; I know most of this file is cut-and-pasted, but this is a
  ;; particularly horrible example.
  (eq bar (car (last (gsharp-buffer:bars (gsharp-buffer:slice bar))))))

(defun find-next-note (note)
  (when (gsharp-buffer:tie-right note)
    (let ((bar (gsharp-buffer:bar (gsharp-buffer:cluster note)))
	  (cluster (gsharp-buffer:cluster note))
	  (next-element nil))
      (loop for (x y) on (gsharp-buffer:elements bar)
	    until (null y)
	    when (eq x cluster) do (setq next-element y))
      (cond
	(next-element)
	((last-bar-p bar) (return-from find-next-note nil))
	(t (let ((next-bar (gsharp-buffer:barno (gsharp-buffer:slice bar)
						(1+ (gsharp-numbering::number bar)))))
	     (if (gsharp-buffer:elements next-bar)
		 (setq next-element (car (gsharp-buffer:elements next-bar)))
		 (return-from find-next-note nil)))))
      ;; now NEXT-ELEMENT is the next element!
      (when (typep next-element 'gsharp-buffer:cluster)
	(loop for n in (gsharp-buffer:notes next-element)
	      if (and (gsharp-buffer:tie-left n)
		      (= (gsharp-buffer:pitch n) (gsharp-buffer:pitch note))
		      (eq (gsharp-buffer:staff n) (gsharp-buffer:staff note))
		      (eq (gsharp-buffer:accidentals n) (gsharp-buffer:accidentals note)))
	      return n)))))
		      
(defun compute-duration (note)
  (loop for n = note then (find-next-note n)
	while n
	sum (gsharp-buffer:duration (gsharp-buffer:cluster n))))

(defun events-from-element (element time channel)
  (when (typep element 'gsharp-buffer:cluster)
    (mapcar (lambda (note)
	      (make-instance 'gsharp-pitched-event
			     :note note
			     :number (gsharp-play::midi-pitch note)
			     :time time
			     :interval (* 4 (compute-duration note))))
	    (remove-if #'gsharp-buffer:tie-left (gsharp-buffer:notes element)))))

(defun events-from-bar (bar time channel)
  (mapcan (lambda (element)
	    (prog1 (events-from-element element time channel)
	      (incf time (* 4 (gsharp-buffer:duration element)))))
	  (gsharp-buffer:elements bar)))

(defun events-from-slice (slice channel durations)
  (let ((time 0))
    (mapcan (lambda (bar duration)
	      (prog1 (events-from-bar bar time channel)
		(incf time (* 4 duration))))
	    (gsharp-buffer:bars slice) durations)))

(defun segment-composition (segment)
  (let* ((slices (mapcar #'gsharp-buffer:body (gsharp-buffer::layers segment)))
	 (durations (gsharp-play::measure-durations slices))
         (gsharp-play::*tuning* (gsharp-buffer:tuning segment))
	 (events (loop for slice in slices
		       for i from 0
		       for events = (events-from-slice slice i durations)
		       then (merge 'list events (events-from-slice slice i durations) 'time<)
		       finally (return events))))
    (let* ((duration (* 4 (reduce #'+ durations)))
	   (result (make-instance 'gsharp-composition 
				  :buffer (gsharp-buffer:buffer segment)
				  ;; FIXME: this will break as soon as
				  ;; gsharp is made to have a sane
				  ;; divisions value in play.lisp
				  ;; instead of 25
				  :tempi (list (make-tempo (* 128 (/ (* 4 25) (gsharp-buffer:tempo segment))) 0 duration))
				  :time 0
				  :interval duration)))
      (sequence:adjust-sequence result (length events)
				:initial-contents events))))

#|

(in-package :clim-user)

(define-command (amuse-play :name t :command-table gsharp::global-gsharp-table)
    ()
  (let* ((segment (gsharp-cursor::segment (gsharp::current-cursor)))
	 (composition (amuse-gsharp::segment-composition segment)))
    (amuse-utils::play composition)))
    
(define-command (infer-key :name t :command-table gsharp::global-gsharp-table)
    ()
  (let* ((segment (gsharp-cursor::segment (gsharp::current-cursor)))
	 (composition (amuse-gsharp::segment-composition segment))
    	 (result (amuse-utils:krumhansl-key-finder composition composition))
	 (name (aref #("C" "C#" "D" "Eb" "E" "F" "F#" "G" "Ab" "A" "Bb" "B") (car result)))
	 (string (format nil "Key: ~A ~(~A~)" name (cadr result))))
    (esa:display-message string))
    

|#