;====================================== ;OM-Lead, 2022-2023 ; ;Library for Rule-based Voice-Leading ;Author: Lorenz Lehmann ;Supervision: Marlon Schumacher ;====================================== (in-package :omlead) (om::defmethod! gen-harmonies ((pitch-set-list list) (instr1 list) (instr2 list) (instr3 list) (instr4 list) &key (avoid-empty-voices nil) (fundamental 6000) (skala (list 100)) (permutations nil) (register-list '(0)) (avoid-doublings nil)) :icon 030719972 :initvals '('((0)) '(6000 7200) nil nil nil) :indoc '("a list of lists of intervals respective to a base not in midi-cents" "range-list with the lowest and highest note of the instrument in midi-cents" "range-list with the lowest and highest note of the instrument in midi-cents" "range-list with the lowest and highest note of the instrument in midi-cents" "range-list with the lowest and highest note of the instrument in midi-cents" "list of intervals based on the virtual fundamental which defines the for register-transposition" "if true all chords with the same note in two or more instruments will be avoided") :numouts 1 :doc "creates a list of chords, that contains all possible transpositions & permutations of the given pitch-sets" (let* ( (instr-list (sort (flat_oml (remove nil (list instr1 instr2 instr3 instr4))) '<)) (total-range (cons (car instr-list) (last instr-list))) (trans-skala (let* ((grundton fundamental) (tief (car total-range)) (hoch (cadr total-range)) (skala-up skala) (skala-down (reverse skala-up)) (endless-up (circular_oml skala-up)) (endless-down (circular_oml skala-down)) (skala-up (loop for i in endless-up sum i into delta until (> (+ delta grundton) hoch) collect i)) (skala-down (loop for i in endless-down sum i into delta until (< (- grundton delta) tief) collect i)) (transpositionsliste-up (list grundton)) (transpositionsliste-down (list grundton))) (loop for i in skala-up do (push (+ (car transpositionsliste-up) i) transpositionsliste-up)) (loop for i in skala-down do (push (- (car transpositionsliste-down) i) transpositionsliste-down)) (append (butlast transpositionsliste-down) (reverse transpositionsliste-up)) )) (harmon-database (om::flat (loop for pitch in trans-skala collect (loop for set in pitch-set-list collect (mapcar #'(lambda (l) (+ pitch l)) set))) 1)) (harmon-database (cond (permutations (om::flat (loop for l in harmon-database collect (permutations_oml l)) 1)) (t harmon-database))) (harmon-database (remove-duplicates (om::flat (loop for a in harmon-database collect (loop for reg in (variations_oml register-list (length a)) collect (mapcar #'(lambda (r p) (+ r p)) reg a))) 1) :test 'equal)) (harmon-database (cond (avoid-doublings (remove nil (loop for a in '((1 2 3 4) (6 6 7 7) (8 8 8 8) (2 3 4 1)) collect (if (not (find-dups_oml a)) a nil)))) (t harmon-database) )) (instr-list2 (list instr1 instr2 instr3 instr4)) (harmon-database (remove -1 (loop for a in harmon-database collect (loop for p in a for c to (1- (length instr-list2)) collect (if (nth c instr-list2) (if (or (< p (car (nth c instr-list2))) (> p (cadr (nth c instr-list2)))) nil p) -1)) ))) (harmon-database (remove nil (loop for a in harmon-database collect (if (> (count nil a) 0) nil a)))) (harmon-database (if avoid-empty-voices (mapcar (lambda (x) (remove -1 x)) harmon-database) harmon-database))) harmon-database)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun circular_oml (items) (setf (cdr (last items)) items) items) (defun flat_oml (liste) (cond ((null (cdr liste)) (if (atom (car liste)) liste (flat_oml (car liste)))) ((and (listp (car liste)) (not (listp (cadr liste)))) (append (car liste) (flat_oml (cdr liste)))) ((and (not (listp (car liste))) (not (listp (cadr liste)))) (append (list (car liste)) (flat_oml (cdr liste)))) ((and (listp (car liste)) (listp (cadr liste))) (append (car liste) (flat_oml (cdr liste)))) ((and (not (listp (car liste))) (listp (cadr liste))) (append (list (car liste)) (flat_oml (cdr liste)))))) (defun get-pos_oml (positions seq) (let ((positions (if (atom positions) (list positions) positions))) (mapcar #'(lambda (it) (nth it seq)) seq))) (defun permutations_oml (bag) (if (null bag) '(()) (mapcan #'(lambda (e) (mapcar #' (lambda (p) (cons e p)) (permutations_oml (remove e bag :count 1 :test #'eq)))) bag))) (defun modulo_oml (pos liste) (append (nthcdr pos liste) (butlast liste (- (length liste) pos)))) (defun register-permut_oml (register-list) (remove-duplicates (om::flat (loop for r in register-list collect (mapcar #'(lambda (l) (permutations_oml (append (make-list l :initial-element r) (make-list (- (length register-list) l) :initial-element 0)))) (loop for x from 1 to (length register-list) collect x))) 2) :test 'equal)) (defun find-pos_oml (item seq) (remove nil (loop for s in seq for x collect (if (equal item s) x)))) (defun sum_oml (liste) (if (null (cdr liste)) (car liste) (+ (car liste) (sum_oml (cdr liste))))) (defun variations_oml (liste pcl) (let* ((liste (remove-duplicates liste)) (liste (make-list pcl :initial-element liste))) (apply #'alexandria:map-product #'list liste))) (defun find-dups_oml (lst) (cond ((null lst) '()) ((member (car lst) (cdr lst)) (cons (car lst) (find-dups_oml (cdr lst)))) (t (find-dups_oml (cdr lst))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;end;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;