Mercurial > hg > amuse
comparison utils/utils.lisp @ 41:90abdf9adb60
monodising and some n-gram utilities
darcs-hash:20070614140028-f76cc-9bdeba6db4097e425b1fee4f58a3327eeb486685.gz
author | David Lewis <d.lewis@gold.ac.uk> |
---|---|
date | Thu, 14 Jun 2007 15:00:28 +0100 |
parents | 262aa7a3d500 |
children | e3d86a0f25b3 |
comparison
equal
deleted
inserted
replaced
40:5bec705db9d6 | 41:90abdf9adb60 |
---|---|
183 (apply substitution-function (list (elt s1 x) (elt s2 y))) | 183 (apply substitution-function (list (elt s1 x) (elt s2 y))) |
184 (if (apply substitution-test (list (elt s1 x) (elt s2 y))) | 184 (if (apply substitution-test (list (elt s1 x) (elt s2 y))) |
185 0 | 185 0 |
186 substitution-cost))))))) | 186 substitution-cost))))))) |
187 (aref d (1- height) (1- width)))) | 187 (aref d (1- height) (1- width)))) |
188 | |
189 ;;;;;;;;;;;;;;;;;;;;;; | |
190 ;; | |
191 ;; More experimental (from amuse-geerdes) | |
192 ;; | |
193 ;; Monody functions | |
194 | |
195 (defun monodificate (composition) | |
196 (let ((events-bags) (latest-cut-off)) | |
197 ;; - Filter out very short notes (<50ms) | |
198 ;; - If there are notes with the same onset time or a large | |
199 ;; proportion (e.g. >25%) of the notes in the segment have | |
200 ;; overlapping durations (of >75%), do for every simultaneous or | |
201 ;; overlapping pair of notes | |
202 ;; -- if one note is louder than the other note (e.g. quieter note | |
203 ;; <75% of louder one) select it as melody note | |
204 ;; -- else select note with higher pitch | |
205 ;; [FIXME: I'm ignoring overlaps for the time being] | |
206 ;; - For non-simultaneous notes with little overlap, set note ends | |
207 ;; to beginning of of onset of next (overlapping) note. | |
208 | |
209 ;; STEP 1: | |
210 ;; `Filter out very short notes (<50ms)' and find `segments' for | |
211 ;; further filtering. | |
212 (sequence::dosequence (event composition) | |
213 (when (> (beats-to-seconds event composition) | |
214 1/20) | |
215 (if (or (not latest-cut-off) | |
216 (time> (onset event) latest-cut-off)) | |
217 (push (list event) events-bags) | |
218 (push event (car events-bags))) | |
219 (when (or (not latest-cut-off) | |
220 (time> (cut-off event) latest-cut-off)) | |
221 (setf latest-cut-off (cut-off event))))) | |
222 ;; Now check each segment for overlaps and | |
223 ;; simultanaieties. N.B. this is a reverse list of reversed | |
224 ;; lists. | |
225 (let ((adjusted-bags)) | |
226 (dolist (events-bag events-bags) | |
227 (setf events-bag (reverse events-bag)) | |
228 (let ((polyphonic-p (check-events-bag-for-polyphony events-bag))) | |
229 (cond | |
230 (polyphonic-p | |
231 (push (resolve-polyphony events-bag composition) adjusted-bags)) | |
232 (t | |
233 (if (cdr events-bag) | |
234 (push (adjust-durations events-bag) adjusted-bags) | |
235 (push events-bag adjusted-bags)))))) | |
236 (apply #'nconc adjusted-bags)))) | |
237 | |
238 (defun resolve-polyphony (event-list composition) | |
239 (do ((i 0 (1+ i))) | |
240 ((>= i (length event-list)) event-list) | |
241 (let ((event (nth i event-list))) | |
242 (do ((j (1+ i) (1+ j))) | |
243 ((or (>= j (length event-list)) | |
244 (time>= (onset (nth j event-list)) | |
245 (cut-off event)))) | |
246 (let* ((event-2 (nth j event-list)) | |
247 (inter-onset (time- (onset event-2) (onset event)))) | |
248 (cond | |
249 ((and inter-onset | |
250 (< (* 2 (duration inter-onset)) | |
251 (duration event)) | |
252 (< (* 2 (duration inter-onset)) | |
253 (duration event-2)) | |
254 (< (beats-to-seconds inter-onset composition) | |
255 1/8)) | |
256 ;; This is clearly polyphony | |
257 (cond | |
258 ((significantly-louderp event-2 event) | |
259 ;; Take event-2 | |
260 (setf event-list (remove event event-list)) | |
261 (decf i) | |
262 (return)) | |
263 ((significantly-louderp event event-2) | |
264 ;; Take event | |
265 (setf event-list (remove event-2 event-list)) | |
266 (decf j)) | |
267 ((pitch> event event-2) | |
268 ;; Take event | |
269 (setf event-list (remove event-2 event-list)) | |
270 (decf j)) | |
271 (t | |
272 ;; Take event-2 | |
273 (setf event-list (remove event event-list)) | |
274 (decf i) | |
275 (return)))) | |
276 (t | |
277 (cond | |
278 ((substantially-louderp event-2 event) | |
279 ;; Take event-2 | |
280 (setf event-list (remove event event-list)) | |
281 (decf i) | |
282 (return)) | |
283 ((substantially-louderp event event-2) | |
284 ;; Take event | |
285 (setf event-list (remove event-2 event-list)) | |
286 (decf j)) | |
287 (t | |
288 ;; Take both | |
289 (let ((event-overlap (period-intersection event event-2))) | |
290 (when event-overlap | |
291 (setf (duration event) | |
292 (duration (time- event-overlap event)))))))))))))) | |
293 | |
294 (defgeneric significantly-louderp (event1 event2) | |
295 ;; noticably louder | |
296 (:method (e1 e2) (declare (ignore e1 e2)) nil)) | |
297 | |
298 (defgeneric substantially-louderp (event1 event2) | |
299 ;; much louder | |
300 (:method (e1 e2) (declare (ignore e1 e2)) nil)) | |
301 | |
302 (defun adjust-durations (events-list) | |
303 (do* ((old-list events-list (cdr old-list)) | |
304 (event (first old-list) (first old-list)) | |
305 (event-2 (second old-list) (second old-list))) | |
306 ((not event-2) events-list) | |
307 (let ((event-overlap (period-intersection event event-2))) | |
308 (when event-overlap | |
309 (setf (duration event) | |
310 (duration (time- event-overlap event))))))) | |
311 | |
312 (defun check-events-bag-for-polyphony (events-bag) | |
313 (let ((overlaps (make-array (length events-bag) :initial-element nil))) | |
314 (when (= (length events-bag) 1) | |
315 ;; obviously no overlaps | |
316 (return-from check-events-bag-for-polyphony nil)) | |
317 (unless (= (length (remove-duplicates events-bag :test #'time=)) | |
318 (length events-bag)) | |
319 ;; Duplicated onsets | |
320 (return-from check-events-bag-for-polyphony 'T)) | |
321 ;; Now for the main bit | |
322 (do* ((events events-bag (cdr events)) | |
323 (i 0 (1+ i)) | |
324 (event (car events) (car events))) | |
325 ((null (cdr events))) | |
326 (unless (and (aref overlaps i) | |
327 (= (aref overlaps i) 1)) | |
328 ;; Would mean we already have a maximal value | |
329 ;; and don't need any more checks | |
330 (do* ((events-2 (cdr events) (cdr events-2)) | |
331 (j (1+ i) (1+ j)) | |
332 (event-2 (car events-2) (car events-2))) | |
333 ((null events-2)) | |
334 (when (time>= (onset event-2) (cut-off event)) | |
335 ;; So no more overlaps | |
336 (return)) | |
337 (let ((shorter (if (duration< event event-2) | |
338 i | |
339 j)) | |
340 (overlap (/ (duration (period-intersection event event-2)) | |
341 (min (duration event) (duration event-2))))) | |
342 ;; only look at pairings for the shorter note. This can | |
343 ;; have odd side effects, but means we never | |
344 ;; under-represent an overlap (I think) | |
345 (when (or (not (aref overlaps shorter)) | |
346 (>= overlap (aref overlaps shorter))) | |
347 (setf (aref overlaps shorter) overlap) | |
348 (when (and (= shorter i) | |
349 (= overlap 1)) | |
350 ;; Maximum value - we can stop | |
351 (return))))))) | |
352 (let ((total 0) (overs 0)) | |
353 (loop for i from 0 to (1- (length events-bag)) | |
354 do (when (aref overlaps i) | |
355 (incf total) | |
356 (when (>= (aref overlaps i) 3/4) | |
357 (incf overs)))) | |
358 (if (and (> total 0) | |
359 (>= (/ overs total) | |
360 1/4)) | |
361 'T | |
362 'nil)))) |