cl-patterns-study/dirty-journal/2022-09-09-maybe-cleanup-ba...

177 lines
6.3 KiB
Common Lisp

(in-package :cl-patterns)
(defun attr-per-phrase (attr-name values &optional (phrase-dur 8))
(pseq (mapcar (lambda (val) (pfindur (pbind attr-name val :dur (pk :dur)) phrase-dur phrase-dur)) values)))
;;; change with previous - another attempt after advice to move :dur higher in outer pattern, that this /should/ pick up (pk :dur)
;; and function wouldn't need dur argument
(defun not-perfect-but-arpeggio (chords &optional (dur 1) (phrase-dur 8))
(parp
(pbind :chord (pseq chords 2)) ; base for arpegio - for each chord next pattern will play out
(psync (pbind :note (pseq (pnary #'nchord (pk :chord)))
:dur (pk :dur) ; yes, that is picked up, if :dur is defined above :embed in the outer pattern, yay
)
phrase-dur phrase-dur)))
;; IV V iii vi
(pb :lets-arpegio-IV-V-iii-vi
:dur 1/2
:embed (not-perfect-but-arpeggio (list :major :minor)) ; each chord plays arpeggio for whole phrase (two bars)
:embed (attr-per-phrase :legato (list 1 0.7)) ; each phrase takes single value for legato
; even if amount of events in phrase change with change of :dur
:embed (attr-per-phrase :root (list 3 4))
)
;; (next-upto-n (pdef :lets-arpegio-iv-v-iii-vi) 30)
;; (play :lets-arpegio-IV-V-iii-vi)
;; (end :lets-arpegio-IV-V-iii-vi)
;; (stop :lets-arpegio-IV-V-iii-vi)
;; Now, if I have totally repeating phrases (like here)
;; I suppose it would be much better to just use PARP to set per phrase attributes?
(pb :lets-arpegio-in-arpegio
(parp (pbind
:legato (pseq (list 1 0.7))
:root (pseq (list 3 2)))
(pbind
:dur 1/3
:embed (not-perfect-but-arpeggio (list :major :minor)))))
;; I already see how this wouldn't be the same!
;; PARP would play both chords :major and :minor for setting of (:legato 1 :root 3) and then again both for setting (:legato 0.7 :root 2)
;; so ATTR-PER-PHRASE does something different
;; yup. generally it does (pseq (list (pfindur (pbind .. value ..)) ..)
;; ok!
;;; now let's clean up bass thingy?
;; pattern (list 4 1/2 1/2 (prest 3))
(defun simple-bass-line (chords strum-pattern)
(parp (pbind :chord (pseq chords 2))
(pbind
:note (pnary #'chord-notes (pk :chord)) ; repeated list of chord notes - played together
:dur (pseq strum-pattern 1))))
(pb :simple-base
:instrument :fmbass
:embed (simple-bass-line (list :major :minor) (list 4 1/2 1/2 (prest 3)))
:embed (attr-per-phrase :root (list 3 2) 8)
:embed (attr-per-phrase :octave (list 3 2) (* 4 2 2))) ; 4 beats per tact, 2 tacts per chord, 2 hard coded chords
(next-upto-n (pdef :simple-base) 40)
;; (play :simple-base)
;; (end :simple-base)
;; (stop :simple-base)
(pdef :new-arpegio-and-bass-1
(ppar (list :lets-arpegio-iv-v-iii-vi :simple-base)))
;; (play :new-arpegio-and-bass-1)
;; (end :new-arpegio-and-bass-1)
;; (stop :new-arpegio-and-bass-1)
;;; notes:
;; arpegio hardcodes 2 repetitions
;; base hardcodes now 2 repetiitons as well, to match with :octave change thing
;; also #'SIMPLE-BASE-LINE could just take in pattern for strum-pattern,
;; not list to be used in #'PSEQ
;;; ok! now let's do 4 bars of same, then 4 bars with 1/3 duration in arpeggios
;; IV V iii vi
;; (setq *my-chords* (list :major :major :minor :minor)
;; *my-roots* (list 3 4 2 5))
;; for now will set in 09-11.lisp
(pb :lets-arpegio-before-duration
:embed (not-perfect-but-arpeggio *my-chords*) ; each chord plays arpeggio for whole phrase (two bars)
:embed (attr-per-phrase :root *my-roots*)
:embed (attr-per-phrase :legato (list 1 0.8 0.6 0.9)) ; each phrase takes single value for legato
; even if amount of events in phrase change with change of :dur
)
;; (next-upto-n (pdef :lets-arpegio-iv-v-iii-vi) 30)
;; (play :lets-arpegio-IV-V-iii-vi)
;; (end :lets-arpegio-IV-V-iii-vi)
;; (stop :lets-arpegio-IV-V-iii-vi)
(pb :arpegio-in-halves
:dur 1/2
:embed :lets-arpegio-before-duration)
(pb :arpegio-in-thirds
:dur 1/4
:embed :lets-arpegio-before-duration)
;; (play :arpegio-in-halves)
;; (stop :arpegio-in-halves)
;; (play :arpegio-in-thirds)
;; (stop :arpegio-in-thirds)
(pb :simple-base-2
:instrument :fmbass
:embed (simple-bass-line *my-chords* (list 4 1/2 1/2 (prest 3)))
:embed (attr-per-phrase :root *my-roots* 8)
:embed (attr-per-phrase :octave (list 3 2) (* 4 2 4))) ; 4 beats per tact, 2 tacts per chord, 4 hard coded chords
(next-upto-n (pdef :simple-base-2) 40)
;; (play :simple-base-2)
;; (end :simple-base-2)
;; (stop :simple-base-2)
;; now. I want 8 bars of base, and 8 bars of arp-in-halves
;; then another 8 bars of base and 8 bars of arp-in-thirds
(pb :arpegios-one-after-another
(pseq (list (pdef :arpegio-in-halves) (pdef :arpegio-in-thirds)) 1))
;; (play :arpegios-one-after-another)
;; (end :arpegios-one-after-another)
;; (stop :arpegios-one-after-another)
(pb :arpegios-and-bass
(ppar (list :arpegios-one-after-another (pn (pdef :simple-base-2) 2))))
;; (play :arpegios-and-bass)
;; (end :arpegios-and-bass)
;; (stop :arpegios-and-bass)
;;; note - and through all of this I'm forgetting about :quant setting
;; that would help align patterns if I start \ end them manually
;; now let's record this and share and get on with the day
;; well, let' copy long recording thingy and just record already
;; https://github.com/byulparan/cl-collider#record-audio-output
;;; write a single channel to disk
;; we can write to buffer number out_buf_num by reading in from the 0 bus
;; (in-package cl-collider)
;; (defsynth disk_writer ((out_buf_num 99))
;; (disk-out.ar out_buf_num (in.ar 0)))
;; (setf mybuffer (buffer-alloc (expt 2 17)))
;; mybuffer
;; ;; start a disk_writer synth
;; (setf writer_0 (synth 'disk_writer))
;; ;; make it output to buffer you allocated
;; (ctrl writer_0 :out_buf_num (bufnum mybuffer))
;; ;; continuously write the buffer contents to a file
;; (buffer-write mybuffer "/tmp/two-arpeggios-and-bass.aiff" :leave-open-p t)
;; ;; now play whatever sounds you like
;; ;; e.g.
;; (in-package :cl-patterns)
;; (play :arpegios-and-bass)
;; (end :arpegios-and-bass)
;; ;; then when you are done
;; (in-package cl-collider)
;; ;; stop the disk_writer synth
;; (free writer_0)
;; ;; close and free the buffer
;; (buffer-close mybuffer)
;; (buffer-free mybuffer)
;; ;; then you can play what you recorded with a utility like mpv:
;; ;; mpv /tmp/foo.aiff