comparison 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
comparison
equal deleted inserted replaced
32:5e705b6f94b6 33:d1010755f507
1 ;;; General purpose utilities 1 ;;; General purpose utilities
2 2
3 (cl:in-package #:amuse-utils) 3 (cl:in-package #:amuse-utils)
4 4
5 ;; Booleans (for filters)
6 (defgeneric pitchedp (event)
7 (:method (e) (declare (ignore e)) nil))
8 (defmethod pitchedp ((event amuse:pitched-event))
9 T)
10 (defgeneric unpitchedp (event)
11 (:method (e) (not (pitchedp e))))
12
13 ;; Rhythm methods
14 (defgeneric crotchets-in-a-bar (time-signature))
15 (defmethod crotchets-in-a-bar ((time-signature basic-time-signature))
16 (let ((num (time-signature-numerator time-signature))
17 (den (time-signature-denominator time-signature)))
18 (* num (/ 4 den))))
19
20 ;; Pitch methods
21
22 (defgeneric sounding-events (anchored-period sequence))
23 (defmethod sounding-events ((anchored-period anchored-period)
24 (sequence composition))
25 (let ((sounding))
26 (sequence:dosequence (event sequence (reverse sounding))
27 (cond
28 ((time>= event (cut-off anchored-period))
29 (return-from sounding-events (reverse sounding)))
30 ((period-intersection anchored-period event)
31 (push event sounding))))))
32
33 (defgeneric midi-pitch-distribution (anchored-period composition))
34 (defmethod midi-pitch-distribution ((anchored-period anchored-period)
35 composition)
36 (let ((pitches (make-array 128 :initial-element 0)))
37 (dolist (event (remove-if #'unpitchedp (sounding-events anchored-period composition)) pitches)
38 (let ((overlap (period-intersection anchored-period event)))
39 (if overlap
40 (incf (aref pitches (midi-pitch-number event))
41 (duration overlap))
42 (if (= (duration event) 0)
43 (format t "~%Note ~D beats in has no duration" (timepoint event))
44 (error "This function has gone wrong - looking for overlaps that don't exist")))))))
45
46 (defgeneric pitch-class-distribution (anchored-period composition))
47 (defmethod pitch-class-distribution ((anchored-period anchored-period)
48 composition)
49 (let ((pitches (make-array 12 :initial-element 0)))
50 (dolist (event (remove-if #'unpitchedp (sounding-events anchored-period composition)) pitches)
51 (let ((overlap (period-intersection anchored-period event)))
52 (if overlap
53 (incf (aref pitches (pitch-class event))
54 (duration overlap))
55 (if (= (duration event) 0)
56 (format t "~%Note ~D beats in has no duration" (timepoint event))
57 (error "This function has gone wrong - looking for overlaps that don't exist")))))))
58
59 (defun normalised-midi-pitch-distribution (object1 object2)
60 (normalise-vector (midi-pitch-distribution object1 object2)))
61 (defun normalised-pitch-class-distribution (object1 object2)
62 (normalise-vector (pitch-class-distribution object1 object2)))
63 (defun normalise-vector (vector &optional (target-sum 1))
64 (let ((total (loop for i from 0 to (1- (length vector))
65 sum (aref vector i))))
66 (cond
67 ((= total target-sum)
68 vector)
69 ((= total 0)
70 (make-array (length vector)
71 :initial-element (/ target-sum (length vector))))
72 (t
73 (map 'vector #'(lambda (x) (* x (/ target-sum total))) vector)))))
74
75 ;; Not as simple as it seems - have to take into account numbering
76 ;; practices and leading silences in representations where bar number
77 ;; isn't part of the explicit structure.
78 (defgeneric bar-number (moment composition))
79
80 (defgeneric bass-note (anchored-period composition))