Mercurial > hg > amuse
diff utils/utils.lisp @ 33:d1010755f507
Large upload of local changes. Many additions, such as harmony and piece-level objects
darcs-hash:20070413100909-f76cc-a8aa8dfc07f438dc0c1a7c45cee7ace2ecc1e6a5.gz
author | David Lewis <d.lewis@gold.ac.uk> |
---|---|
date | Fri, 13 Apr 2007 11:09:09 +0100 |
parents | e2e19baba730 |
children | ad321ce17e3e |
line wrap: on
line diff
--- a/utils/utils.lisp Mon Dec 18 13:23:31 2006 +0000 +++ b/utils/utils.lisp Fri Apr 13 11:09:09 2007 +0100 @@ -2,3 +2,79 @@ (cl:in-package #:amuse-utils) +;; Booleans (for filters) +(defgeneric pitchedp (event) + (:method (e) (declare (ignore e)) nil)) +(defmethod pitchedp ((event amuse:pitched-event)) + T) +(defgeneric unpitchedp (event) + (:method (e) (not (pitchedp e)))) + +;; Rhythm methods +(defgeneric crotchets-in-a-bar (time-signature)) +(defmethod crotchets-in-a-bar ((time-signature basic-time-signature)) + (let ((num (time-signature-numerator time-signature)) + (den (time-signature-denominator time-signature))) + (* num (/ 4 den)))) + +;; Pitch methods + +(defgeneric sounding-events (anchored-period sequence)) +(defmethod sounding-events ((anchored-period anchored-period) + (sequence composition)) + (let ((sounding)) + (sequence:dosequence (event sequence (reverse sounding)) + (cond + ((time>= event (cut-off anchored-period)) + (return-from sounding-events (reverse sounding))) + ((period-intersection anchored-period event) + (push event sounding)))))) + +(defgeneric midi-pitch-distribution (anchored-period composition)) +(defmethod midi-pitch-distribution ((anchored-period anchored-period) + composition) + (let ((pitches (make-array 128 :initial-element 0))) + (dolist (event (remove-if #'unpitchedp (sounding-events anchored-period composition)) pitches) + (let ((overlap (period-intersection anchored-period event))) + (if overlap + (incf (aref pitches (midi-pitch-number event)) + (duration overlap)) + (if (= (duration event) 0) + (format t "~%Note ~D beats in has no duration" (timepoint event)) + (error "This function has gone wrong - looking for overlaps that don't exist"))))))) + +(defgeneric pitch-class-distribution (anchored-period composition)) +(defmethod pitch-class-distribution ((anchored-period anchored-period) + composition) + (let ((pitches (make-array 12 :initial-element 0))) + (dolist (event (remove-if #'unpitchedp (sounding-events anchored-period composition)) pitches) + (let ((overlap (period-intersection anchored-period event))) + (if overlap + (incf (aref pitches (pitch-class event)) + (duration overlap)) + (if (= (duration event) 0) + (format t "~%Note ~D beats in has no duration" (timepoint event)) + (error "This function has gone wrong - looking for overlaps that don't exist"))))))) + +(defun normalised-midi-pitch-distribution (object1 object2) + (normalise-vector (midi-pitch-distribution object1 object2))) +(defun normalised-pitch-class-distribution (object1 object2) + (normalise-vector (pitch-class-distribution object1 object2))) +(defun normalise-vector (vector &optional (target-sum 1)) + (let ((total (loop for i from 0 to (1- (length vector)) + sum (aref vector i)))) + (cond + ((= total target-sum) + vector) + ((= total 0) + (make-array (length vector) + :initial-element (/ target-sum (length vector)))) + (t + (map 'vector #'(lambda (x) (* x (/ target-sum total))) vector))))) + +;; Not as simple as it seems - have to take into account numbering +;; practices and leading silences in representations where bar number +;; isn't part of the explicit structure. +(defgeneric bar-number (moment composition)) + +(defgeneric bass-note (anchored-period composition)) \ No newline at end of file