Compare commits
8 Commits
38eab3f355
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b07c84a2f7 | ||
|
|
adb02840ba | ||
|
|
e6270ea435 | ||
|
|
00515cd9df | ||
|
|
788c27c54b | ||
|
|
12f0c80af7 | ||
|
|
6a9b9a88c4 | ||
|
|
0ae86a5f51 |
12
README.org
Normal file
12
README.org
Normal file
@@ -0,0 +1,12 @@
|
||||
#+title: Learning music with cl-patterns & cl-collider
|
||||
* structure of files here
|
||||
** dirty-journal
|
||||
per-day lisp files and single org-journal as I'm figuring things out for the first time
|
||||
** stabler-things
|
||||
cleaned up definitions and functions, saved for possible reuse
|
||||
1. setting-up.lisp
|
||||
What I evaluate to start up and test setup
|
||||
2. synthesizer.lisp
|
||||
single collection of definitions for instruments
|
||||
** and hopefully there will be cleaned up journal
|
||||
that would separate significant things I've been figuring out in a form that would be helpful for other to figure them out
|
||||
@@ -1,10 +1,6 @@
|
||||
(in-package #:cl-collider)
|
||||
;; https://github.com/SCLOrkHub/SCLOrkSynths
|
||||
;; https://github.com/SCLOrkHub/SCLOrkSynths/blob/master/SynthDefs/strings/violin.scd
|
||||
(freq 440) (gate 1) (amp 1) (pan 0) (out 0) (att 0.1) (dec 0.1) (sus 0.5) (rel 0.1)
|
||||
(vRate 4.6) (vDepth 0.02) (vAtt 0.15) (vRateVar 0.25) (vDepthVar 0.05)
|
||||
(pwmVarRate 2) (pwmMin 0.7) (pwmMax 0.8) (pwmRate 5)
|
||||
(bridgeFreq 2500) (scratchDepth 0.15)
|
||||
|
||||
(defsynth violin ((freq 440) (gate 1) (amp 1) (pan 0) (out 0) (att 0.1) (dec 0.1) (sus 0.5) (rel 0.1)
|
||||
(vRate 4.6) (vDepth 0.02) (vAtt 0.15) (vRateVar 0.25) (vDepthVar 0.05)
|
||||
@@ -20,8 +16,8 @@
|
||||
(range (lf-pulse.ar (* freq 1.5)) (/ 1 scratch) scratch))))
|
||||
(snd-step-2 (+ (* snd-step-1 0.7)
|
||||
(bpf.ar snd-step-1 bridgeFreq 2 2)))
|
||||
(snd-step-3 (* snd-step-2 envelope)))
|
||||
(out.ar out (pan2.ar snd-step-3 pan)))))
|
||||
(snd-step-3 (* snd-step-2 amp envelope)))
|
||||
(out.ar out (pan2.ar snd-step-3 pan))))
|
||||
;; (synth :violin :freq 400)
|
||||
;; (stop)
|
||||
(in-package #:cl-patterns)
|
||||
@@ -31,9 +27,10 @@
|
||||
:decay 2
|
||||
:att 0.07
|
||||
:sus 0.8
|
||||
:amp 0.1
|
||||
:legato 1
|
||||
:degree (pseq (list 0 1 2 3 4 5 6 7) 1)
|
||||
:dur 2)
|
||||
:dur 1)
|
||||
;; (play :foo-with-pluck-synth)
|
||||
;; (end :foo-with-pluck-synth)
|
||||
;; (stop :foo-with-pluck-synth)
|
||||
@@ -236,9 +236,9 @@
|
||||
:instrument :fmrhodes1
|
||||
:octave 3
|
||||
:degree (pseq (list 0 1 4 8 (prest 0) 0 2 4 7 4 2) 1))
|
||||
(play :hm-lallaa)
|
||||
(end :hm-lallaa)
|
||||
(stop :hm-lallaa)
|
||||
;; (play :hm-lallaa)
|
||||
;; (end :hm-lallaa)
|
||||
;; (stop :hm-lallaa)
|
||||
;; yup, that's a pause, cool
|
||||
;; so, do I bring that stuff into a separate file?
|
||||
|
||||
@@ -252,7 +252,7 @@
|
||||
|
||||
(defun nchord (symbol &optional (base 0))
|
||||
"Return list of notes for chord names by SYMBOL over the BASE."
|
||||
(mapcar (lambda (note) (+ base note)) (chord-notes symbol)))
|
||||
(mapcar (lambda (note) (+ base note)) (chord-notes (chord symbol))))
|
||||
|
||||
(nchord :major 3)
|
||||
|
||||
@@ -265,9 +265,9 @@
|
||||
:base 2
|
||||
:root 5
|
||||
)
|
||||
(play :hm-chords-progression)
|
||||
(end :hm-chords-progression)
|
||||
(stop :hm-chords-progression)
|
||||
;; (play :hm-chords-progression)
|
||||
;; (end :hm-chords-progression)
|
||||
;; (stop :hm-chords-progression)
|
||||
|
||||
;; so, what's a good way to use them? just wrap separately into #'CHORD-NOTES
|
||||
;; maybe at least for now
|
||||
@@ -291,9 +291,9 @@
|
||||
:base 2
|
||||
:root 5
|
||||
)
|
||||
(play :hm-chords-progress-em-g-am-c)
|
||||
(end :hm-chords-progress-em-g-am-c)
|
||||
(stop :hm-chords-progress-em-g-am-c)
|
||||
;; (play :hm-chords-progress-em-g-am-c)
|
||||
;; (end :hm-chords-progress-em-g-am-c)
|
||||
;; (stop :hm-chords-progress-em-g-am-c)
|
||||
|
||||
;; Am – F – C – G (i – VI – III – VII)
|
||||
(pb :hm-chords-progress-am-f-c-g
|
||||
@@ -306,24 +306,27 @@
|
||||
:base 2
|
||||
:root 5
|
||||
)
|
||||
(play :hm-chords-progress-am-f-c-g)
|
||||
(end :hm-chords-progress-am-f-c-g)
|
||||
(stop :hm-chords-progress-am-f-c-g)
|
||||
;; (play :hm-chords-progress-am-f-c-g)
|
||||
;; (end :hm-chords-progress-am-f-c-g)
|
||||
;; (stop :hm-chords-progress-am-f-c-g)
|
||||
|
||||
;; IV V iii vi (from video on japan's favourite chord progression)
|
||||
;; https://youtu.be/6aezSL_GvZA
|
||||
(pb :hm-chords-progress-golden-road
|
||||
:instrument :strings
|
||||
;; :instrument :violin
|
||||
:instrument :fmrhodes1
|
||||
:octave 4
|
||||
:amp 0.2
|
||||
:legato 1
|
||||
;; :degree (pseq (mapcar #'chord-notes (list :major :minor :maj7 :major)) 1) ; works, but can't insert (prest 0) among chords
|
||||
;; :degree (pseq (list (chord :major) (chord :minor) (chord :maj7) (chord :major)) 1) ; doesn't seem to work
|
||||
:degree (pseq (list (nchord :major 3) (nchord :major 4) (nchord :minor 2) (nchord :minor 5) ) 1) ; doesn't seem to work
|
||||
;; :degree (pseq (list 1 2 3) 1) ; doesn't seem to work
|
||||
:dur (pseq (list 4 4 4 4 ))
|
||||
:root 0)
|
||||
(play :hm-chords-progress-golden-road)
|
||||
(end :hm-chords-progress-golden-road)
|
||||
(stop :hm-chords-progress-golden-road)
|
||||
;; (play :hm-chords-progress-golden-road)
|
||||
;; (end :hm-chords-progress-golden-road)
|
||||
;; (stop :hm-chords-progress-golden-road)
|
||||
|
||||
;; does it sound like in the video then?
|
||||
|
||||
@@ -332,3 +335,11 @@
|
||||
;; - giving (note/chord) and rhythm to get form that single note
|
||||
|
||||
;; latter should be possible from defining a subpattern? with static note?
|
||||
|
||||
;;; now, I'd like to use (render (pdef :your-pattern) "/path/to/output.wav" :dur 4)
|
||||
;; for that I'd need to use more recent version than I get from quicklisp, so clone repo
|
||||
quicklisp:*local-project-directories*
|
||||
(ql:register-local-projects)
|
||||
(ql:where-is-system :cl-patterns) ;; #P"/home/efim/quicklisp/local-projects/cl-patterns/"
|
||||
|
||||
;; (render (pdef :hm-chords-progress-golden-road) "/tmp/chords-4.wav" :dur 16)
|
||||
130
dirty-journal/2022-09-05-maybe-sequences-from-chords.lisp
Normal file
130
dirty-journal/2022-09-05-maybe-sequences-from-chords.lisp
Normal file
@@ -0,0 +1,130 @@
|
||||
|
||||
(in-package #:cl-patterns)
|
||||
|
||||
(pb :notes
|
||||
:degree (pseq (list 0 1 2 3) 1))
|
||||
;; (play :notes)
|
||||
;; (stop :notes)
|
||||
|
||||
(setq *notes* (pseq (list 0 1 2 3)))
|
||||
(pb :just-*notes*
|
||||
:degree *notes*)
|
||||
;; (play :just-*notes*)
|
||||
;; (stop :just-*notes*)
|
||||
;;
|
||||
;; but that would certainly not help with changing other params
|
||||
;; "per phrase"
|
||||
|
||||
|
||||
(pb :attempt-at-repeating-pattern
|
||||
:degree (pseq (list 0 1 2 3) 2)
|
||||
:octave (pr (pwhite 2 5))
|
||||
)
|
||||
;; (play :attempt-at-repeating-pattern)
|
||||
;; (end :attempt-at-repeating-pattern)
|
||||
;; (stop :attempt-at-repeating-pattern)
|
||||
|
||||
;; how does that work? why octave only changes after the degree pseq ends?
|
||||
|
||||
(in-package #:cl-patterns)
|
||||
;; (next-upto-n (pr (pwhite 2 7) (pseq '(1 3 0 2) 1)))
|
||||
;; this started some computations in sbcl, which are in backgournd and I don't know how to stop
|
||||
;; (defpattern pr (pattern)
|
||||
;; (pattern
|
||||
;; (repeats :initform :inf)
|
||||
;; (current-value :state t :initform nil)
|
||||
;; (current-repeats-remaining :state t))
|
||||
;; :documentation "Repeat each value from PATTERN REPEATS times. If REPEATS is 0, the value is skipped.
|
||||
|
||||
;; Example:
|
||||
|
||||
;; (next-upto-n (pr (pseries) (pseq '(1 3 0 2) 1)))
|
||||
;; ;=> (0 1 1 1 3 3)
|
||||
|
||||
;; See also: `pdurstutter', `pn', `pdrop', `parp'")
|
||||
|
||||
(in-package #:cl-patterns)
|
||||
(next-upto-n (pseq '(1 2 3) 6) 4)
|
||||
(next-upto-n (pwhite 2 7) 4)
|
||||
(next-upto-n (pr (pwhite 2 7) 3) 7)
|
||||
(next-upto-n (pr (pwhite 2 7) (list 1 2 3)) 7)
|
||||
(next-upto-n (pr (pwhite 2 7) (pseq '(1 3 0 2) 1)) 10) ; still not working?
|
||||
(next-upto-n (pr (pwhite 2 7) (pseq '(1 3 0 2) 1)) 6) ; for some reason works up to 6
|
||||
(next-upto-n (pr (pwhite 2 7) (pseq '(1 3 0 2) 1)) 7) ; for some reason works up to 6
|
||||
;;; so, if I go into M-x sly-list-threads - I see worker threads,
|
||||
;;; and I could kill them, but also could d for debug, and "return value from thread", then that value is appended as 7th iteam
|
||||
;;; so the stream gets frozen, waiting for something to compute?
|
||||
; well, I guess OBJECT is stream that always repeats itself
|
||||
; so when I just put 3 or 4 - that's endless stream of 3s and 4s
|
||||
;; and to have pseq work - I need to remove that "1" and pseq would repeat forever, and numbers from pseq would be "multipliers" for endless stream of random numbers
|
||||
;; and random numbers would be new for second circle?
|
||||
|
||||
(next-upto-n (pr (pwhite 2 7) (pseq '(1 3 0 2) 2)) 7) ; yep
|
||||
(next-upto-n (pr (pwhite 2 7) (pseq '(1 3 0 2))) 17) ; yep
|
||||
|
||||
;; so when "automatic jazz" https://github.com/defaultxr/cl-patterns/blob/master/doc/cookbook.org#random-notes-from-a-scale
|
||||
;; does :octave (pr (pwhite 2 7))
|
||||
;; that means repeat (randomly selected from 2 to 7) "forever/until end of pattern"
|
||||
;; and end of pattern doesn't come from the :octave or :root
|
||||
;; but comes from the fact that #'PSHUF for :note has "end after 4"
|
||||
;; cool
|
||||
|
||||
;; so to have sequence of parameters that apply for whole melody
|
||||
;; I'd need "pr forever" and then take items from the list, so from pseq
|
||||
|
||||
(pb :at-repeating-pattern
|
||||
;; :degree (pseq (list 0 1 2 3) 2)
|
||||
:note (pshuf (scale-notes :minor) 1)
|
||||
:octave (pr (pseq (list 3 4 5)))
|
||||
)
|
||||
;; (play :at-repeating-pattern)
|
||||
;; (end :at-repeating-pattern)
|
||||
;; (stop :at-repeating-pattern)
|
||||
|
||||
(next-upto-n (pdef :at-repeating-pattern) 20)
|
||||
;; well, no, I don't understand after all!
|
||||
;; the pattern ends when :degree or :note part ends, and not restarts
|
||||
;; let's just copy "automatic jazz" and view it with #'NEXT-UPTO-N
|
||||
|
||||
(pb :automatic-jazz
|
||||
:note (pshuf (scale-notes :minor) 4)
|
||||
:octave (pr (pwhite 2 7))
|
||||
:root (pr (pwhite 0 12))
|
||||
:dur (pshuf (list 1/3 1/4)))
|
||||
;; (play :automatic-jazz)
|
||||
;; (end :automatic-jazz)
|
||||
;; (stop :automatic-jazz)
|
||||
|
||||
(next-upto-n (pdef :automatic-jazz) 30)
|
||||
;; well, maybe pr only doesn't work with pseq, since it always selects first from the stream?
|
||||
|
||||
(pb :at-with-random-repeating-pattern
|
||||
:degree (pseq (list 0 1 2 3) 2)
|
||||
:octave (pr (pwhite 3 5))
|
||||
)
|
||||
;; (play :at-with-random-repeating-pattern)
|
||||
;; (end :at-with-random-repeating-pattern)
|
||||
;; (stop :at-with-random-repeating-pattern)
|
||||
|
||||
;;; hm, not exactly what I imagined in a way of combining patterns
|
||||
|
||||
;; then I guess, I want the melody to repeat in pseq endlessly, and match pr repeat size to length of melody (in events, and not beats, alas!)
|
||||
;; and use something like pxrand and end with end of pxrands
|
||||
;; even though that is not yet satisfactory, let's try it
|
||||
|
||||
(pb :at-with-outside-pseq-repeating-pattern
|
||||
;; :degree (pseq (list 0 1 2 3))
|
||||
:degree (pseq (list 0 1 2 (list 0 7)))
|
||||
:octave (pr (pseq (list 3 4 5 4 3)) 4)
|
||||
:amp (pseq (list 0.7 0.5 0.5 0.5)))
|
||||
;; (play :at-with-outside-pseq-repeating-pattern)
|
||||
;; (end :at-with-outside-pseq-repeating-pattern)
|
||||
;; (stop :at-with-outside-pseq-repeating-pattern)
|
||||
(next-upto-n (pdef :at-with-outside-pseq-repeating-pattern) 12)
|
||||
|
||||
;; so I guess when the pattern "repeats" it will be "exactly same" with randoms recalculated
|
||||
;; also - can I save the seeds? in case I'd like to record a random sequence that I liked on the walkthough?
|
||||
|
||||
;; also - how would I specify "a multiplier" for durations? if the notes are not of the same duration
|
||||
|
||||
;; (render (pdef :at-with-outside-pseq-repeating-pattern) "/tmp/repeating-4.wav" :dur 16)
|
||||
101
dirty-journal/2022-09-06-maybe-chord-melodies.lisp
Normal file
101
dirty-journal/2022-09-06-maybe-chord-melodies.lisp
Normal file
@@ -0,0 +1,101 @@
|
||||
|
||||
(in-package :cl-patterns)
|
||||
(all-instruments)
|
||||
(all-chords)
|
||||
|
||||
(nchord :major 3) ; so, i could then inject / what's the verb
|
||||
; splice list as notes
|
||||
(nchord "Dominant 7th" 2)
|
||||
(chord :major)
|
||||
(chord "Major Triad")
|
||||
|
||||
(chord-indexes :major) ; (0 2 4) this goes into :degree
|
||||
(chord-notes :major) ; (0 4 7) and this goes into :notes?
|
||||
(chord-midinotes :major)
|
||||
|
||||
;; (pb :first-try-sequencing
|
||||
;; )
|
||||
|
||||
;; i want something like
|
||||
;; (pb
|
||||
;; :degree chorded-arpeggio '(0 1 3 2 3 0)
|
||||
|
||||
;; ok, let's settle situation with notes vs degrees
|
||||
(pb :with-notes
|
||||
:instrument :fmrhodes1
|
||||
;; :note (pseq (list 0 1 2 3 4 5 6 7) 1))
|
||||
;; :note (pseq (list 0 2 4 5 7 9 11 12) 1)
|
||||
:note (pseq (list 0 2 4 5 7 9 11 12) 1))
|
||||
;; (play :with-notes)
|
||||
;; (end :with-notes)
|
||||
;; (stop :with-notes)
|
||||
;; not whole octave from 0 to 7, so every key one after anothe
|
||||
;; and that would be just tuning steps, not taking into account the "lad"
|
||||
;; 0 2 4 5 7 9 11 12 is the major. ok
|
||||
|
||||
(pb :with-degrees
|
||||
:instrument :fmrhodes1
|
||||
:degree (pseq (list 0 1 2 3 4 5 6 7) 1))
|
||||
;; (play :with-degrees)
|
||||
;; (end :with-degrees)
|
||||
;; (stop :with-degrees)
|
||||
|
||||
;; so if I take 'chord-notes' in nchord, i need to use :note
|
||||
;; in the pattern
|
||||
|
||||
;; yay, and the patterns from 09-04 sound much better now
|
||||
|
||||
;;; so, back to arpeggio things
|
||||
;; i'd want something like
|
||||
;; (pb :hopes-for-arpegio
|
||||
;; :note (arpegio-thingy (list 0 2 3 1 3 0))
|
||||
;; :dur (pseq (list 1 1 2 1 1 2))
|
||||
;; :chords (pseq (list :maj :min :maj7 :maj6 :maj)))
|
||||
|
||||
;;; and then maybe have only :note and :dur as one names pattern
|
||||
;; which somehow later combines with the :chords pseq
|
||||
|
||||
;; (defpattern pfunc (pattern)
|
||||
;; ((func :type function-designator)
|
||||
;; (length :initform :inf)
|
||||
;; (current-repeats-remaining :state t))
|
||||
;; :documentation "Yield the result of evaluating FUNC. Note that the current event of the parent pattern is still accessible via the `*event*' special variable.
|
||||
|
||||
;; Example:
|
||||
|
||||
(next-upto-n (pfunc (lambda () (random 10)) 4))
|
||||
;=> ((5 2 8 9))
|
||||
|
||||
;; (next-upto-n (pbind :foo (pwhite 0 10 4)
|
||||
;; :bar (pfunc (lambda ()
|
||||
;; (if (> (event-value *event* :foo) 5) :greater :lesser)))))
|
||||
;; ;=> ((EVENT :FOO 0 :BAR :LESSER) (EVENT :FOO 6 :BAR :GREATER)
|
||||
;; (EVENT :FOO 7 :BAR :GREATER) (EVENT :FOO 8 :BAR :GREATER))
|
||||
|
||||
;; See also: `pf', `pnary', `plazy', `pif'")
|
||||
|
||||
;;; so, maybe that's the way?
|
||||
;; I really could have :chord attribute, and could possibly have :arpeggio-steps attribute
|
||||
;; and those would combine to create :note attribute
|
||||
|
||||
;; i was recommended PARP
|
||||
;; but I don't understand how it could be used in conjunction with chords?
|
||||
;; well, no, I see - I could change :octave, and in first pattern return :notes, right?
|
||||
|
||||
(chord-notes :major)
|
||||
|
||||
;;; full on gift of help:
|
||||
(pdef :foo
|
||||
(parp (pbind :note (pnary #'chord-notes (pseq (list :major :minor :maj7 :maj6 :major) 1))
|
||||
:dur (pseq (list 1 1 2 1 1 2)))
|
||||
(pbind :note (p+ (pk :note)
|
||||
(pseq (list 0 2 3 1 3 0) 1)))))
|
||||
(next-upto-n (pdef :foo) 4)
|
||||
;; (play :foo)
|
||||
;; (end :foo)
|
||||
;; (stop :foo)
|
||||
|
||||
(next-upto-n (pbind :note (p+ 1 (pseq (list 0 2 3) 1))) 4)
|
||||
|
||||
;; let's try to get sequence of steps when we give as input notes of a chord
|
||||
;; tomorrow
|
||||
89
dirty-journal/2022-09-07-trying-more-arpegioing-chords.lisp
Normal file
89
dirty-journal/2022-09-07-trying-more-arpegioing-chords.lisp
Normal file
@@ -0,0 +1,89 @@
|
||||
|
||||
;; let's try the pfunc to create arpegio from the chord
|
||||
(in-package :cl-patterns)
|
||||
(next-upto-n (pbind :chord (pseq (list :major :minor :minor-triad :major))
|
||||
:note (pfunc (lambda ()
|
||||
(let* ((chord (event-value *event* :chord))
|
||||
(notes (nchord chord)))
|
||||
;; let's keep it simple for a moment
|
||||
notes))
|
||||
)) 10)
|
||||
;; ((EVENT :CHORD :MAJOR :NOTE (0 4 7)) (EVENT :CHORD :MINOR :NOTE (0 3 7))
|
||||
;; (EVENT :CHORD :MINOR-TRIAD :NOTE (0 3 7)) (EVENT :CHORD :MAJOR :NOTE (0 4 7))
|
||||
;; (EVENT :CHORD :MAJOR :NOTE (0 4 7)) (EVENT :CHORD :MINOR :NOTE (0 3 7))
|
||||
;; (EVENT :CHORD :MINOR-TRIAD :NOTE (0 3 7)) (EVENT :CHORD :MAJOR :NOTE (0 4 7))
|
||||
;; (EVENT :CHORD :MAJOR :NOTE (0 4 7)) (EVENT :CHORD :MINOR :NOTE (0 3 7)))
|
||||
|
||||
;; And I'd still in parp generator
|
||||
(next-upto-n (parp (pbind :chord (pseq (list :minor-triad :major)))
|
||||
(pbind :note (pfunc (lambda ()
|
||||
(let* ((chord (event-value *event* :chord))
|
||||
(notes (nchord chord)))
|
||||
;; let's keep it simple for a moment
|
||||
(pseq notes 1)))
|
||||
))) 10)
|
||||
;; for some reason this stays on first chord forever, but does arpegio
|
||||
;; bit of something I don't understand
|
||||
|
||||
(next-upto-n (parp (pbind :ocatave (pseq (list 3 4 3 5)))
|
||||
(pbind :note (pseq (list 0 1 2) 1))) 12) ; needed 1 repeat limit here
|
||||
|
||||
;; let's try with #'PK
|
||||
(next-upto-n (parp (pbind :chord (pseq (list :minor-triad :major)))
|
||||
(pbind :note (let* ((chord (pk :chord))
|
||||
(notes (nchord chord)))
|
||||
;; let's keep it simple for a moment
|
||||
(pseq notes 1)))) 10)
|
||||
;; error, no applicable method
|
||||
;; how does that work then?
|
||||
|
||||
(pdef :foo
|
||||
(parp (pbind :note (pnary #'chord-notes (pseq (list :major :minor :maj7 :maj6 :major) 1))
|
||||
:dur (pseq (list 1 1 2 1 1 2)))
|
||||
(pbind :note (p+ (pk :note)
|
||||
(pseq (list 0 2 3 1 3 0) 1)))))
|
||||
(next-upto-n (pdef :foo) 10)
|
||||
;; and what if I change :note to :chord here?
|
||||
|
||||
(next-upto-n (pdef :foo
|
||||
(parp (pbind :chord (pnary #'chord-notes (pseq (list :major :minor :maj7 :maj6 :major) 1))
|
||||
:dur (pseq (list 1 1 2 1 1 2)))
|
||||
(pbind :note (p+ (pk :chord)
|
||||
(pseq (list 0 2 3 1 3 0) 1))))) 10)
|
||||
|
||||
;; maybe difference is that #'LET* can't be directly in the place that defined :note?
|
||||
;; and I should use #'PSEQ and move #'LET* into list definiton?
|
||||
(next-upto-n (parp (pbind :chord (pseq (list :minor-triad :major)))
|
||||
(pbind :note (pseq (let* ((chord (pk :chord))
|
||||
(notes (nchord chord)))
|
||||
notes)
|
||||
1)))
|
||||
10)
|
||||
;; or maybe (pk :chord) is a pattern and can't be used as "just function to get value"
|
||||
;; seems true
|
||||
(next-upto-n (parp (pbind :chord (pseq (list :minor-triad :major)))
|
||||
(pbind :note (pk :chord)))
|
||||
10)
|
||||
;; here pk :chord is object so, endless pattern and we never switch to :major
|
||||
;; but that's ok,
|
||||
;; main lesson I guess that I need to use pattern transformation functions,
|
||||
;; and lisp transformations mainly on arguments
|
||||
|
||||
(next-upto-n (parp (pbind :chord (pseq (list :minor-triad :major)))
|
||||
(pbind :note (pfunc (lambda ()
|
||||
(pseq (nchord (event-value *event* :chord)) 1)))))
|
||||
10)
|
||||
;; endless stream, inner :note doesn't end?
|
||||
(next-upto-n (parp (pbind :chord (pseq (list :minor-triad :major)))
|
||||
(pbind :note (pseq (pnary #'nchord (pk :chord)) 2)))
|
||||
20)
|
||||
;; not that seems to work?
|
||||
(pdef :maybe-arpegio
|
||||
(parp (pbind :chord (pseq (list :minor-triad :major) 2))
|
||||
(pbind :note (pseq (pnary #'nchord (pk :chord)) 2))))
|
||||
;; (play :maybe-arpegio)
|
||||
;; (end :maybe-arpegio)
|
||||
;; (stop :maybe-arpegio)
|
||||
|
||||
;; could I maybe now insert this into a pb
|
||||
;; so that I could change speed and root for whole thing?
|
||||
532
dirty-journal/2022-09-08-more-on-chord-melodies.lisp
Normal file
532
dirty-journal/2022-09-08-more-on-chord-melodies.lisp
Normal file
@@ -0,0 +1,532 @@
|
||||
|
||||
(in-package :cl-patterns)
|
||||
|
||||
(pdef :maybe-arpegio
|
||||
(parp (pbind :chord (pseq (list :minor-triad :major) 2))
|
||||
(pbind :note (pseq (pnary #'nchord (pk :chord)) 2))))
|
||||
;; (play :maybe-arpegio)
|
||||
;; (end :maybe-arpegio)
|
||||
;; (stop :maybe-arpegio)
|
||||
(next-upto-n (pdef :maybe-arpegio) 10)
|
||||
|
||||
;; now about including patterns one into another, can I reference this pattern
|
||||
;; in another which would specify an instrument?
|
||||
;; judging by https://github.com/defaultxr/cl-patterns/blob/master/doc/patterns.org
|
||||
;; maybe #'PSYM or #'PPAR would help?
|
||||
|
||||
(pb :legato-keys
|
||||
:legato 1
|
||||
:instrument :fmrhodes1)
|
||||
|
||||
(pdef :maybe-joined-patterns (psym (ppar (list :maybe-arpegio :legato-keys))))
|
||||
;; (play :maybe-joined-patterns)
|
||||
;; (end :maybe-joined-patterns)
|
||||
;; (stop :maybe-joined-patterns)
|
||||
|
||||
;; nope, they just play in parallel, :legato-keys plays single note,
|
||||
;; how would I merge them into a single pattern \ stream?
|
||||
|
||||
;;; maybe #'IPSTREAM ?
|
||||
(pdef :attempt-2-at-joining (ipstream (list (pdef :maybe-arpegio) (pdef :legato-keys))))
|
||||
;; (play :attempt-2-at-joining)
|
||||
;; (stop :attempt-2-at-joining)
|
||||
;; nope.
|
||||
;; (and I actually can use #NEXT-UPTO-N to introspect
|
||||
|
||||
(next-upto-n (pdef :maybe-joined-patterns) 10)
|
||||
(next-upto-n (pdef :attempt-2-at-joining) 10) ; also has EVENT :TYPE :REST inserted
|
||||
|
||||
;;; what about #'PMETA ?
|
||||
;; nope
|
||||
;;; let's check how #'PBIND works, it might just be able to extend existing patterns
|
||||
;; looking at #'PBIND code I saw ":embed" key and went searching through the file
|
||||
;; and found this:
|
||||
;;
|
||||
;;; pchain
|
||||
;; :documentation Combine multiple patterns into one event stream.
|
||||
;; (next-n (pchain (pbind :foo (pseq '(1 2 3))) (pbind :bar (pseq '(7 8 9) 1))) 4)
|
||||
;;
|
||||
;; ;=> ((EVENT :FOO 1 :BAR 7) (EVENT :FOO 2 :BAR 8) (EVENT :FOO 3 :BAR 9) NIL)
|
||||
;; "see also pbind :embed key"
|
||||
;;
|
||||
;; So I don't know what :embed does, but pchain seems to be what I need, right?
|
||||
;;
|
||||
;; from the "patterns.org" : pchain - Chain patterns together by using the first source pattern’s output as the input to the second, etc.
|
||||
;; didn't seem like the thing
|
||||
|
||||
;;; let's try it
|
||||
(pdef :attempt-3
|
||||
(pchain (pdef :legato-keys) (pdef :maybe-arpegio)))
|
||||
(next-upto-n (pdef :attempt-3) 10)
|
||||
;; (play :attempt-3)
|
||||
;; (end :attempt-3)
|
||||
;; (stop :attempt-3)
|
||||
|
||||
;; that's it!
|
||||
;; now let's try :embed ?
|
||||
|
||||
(pb :attempt-4
|
||||
:instrument :fmrhodes1
|
||||
:legato 1
|
||||
:embed :maybe-arpegio)
|
||||
;; (play :attempt-4)
|
||||
;; (end :attempt-4)
|
||||
;; this also works, yay!
|
||||
;; now, can I have several :embed arguments?
|
||||
|
||||
(pbind :dur 2) ; so #'PBIND "binds keys to patterns"
|
||||
(pdef :with-lengths
|
||||
(pbind :dur 2)) ; #'PDEF gives this name
|
||||
; and takes in patterns, so can take in "pattern-constructors"
|
||||
(pb :with-lengths-2
|
||||
:dur 2) ; is a shorthand
|
||||
; where we can use "pattern-combiners" for each key anyway
|
||||
|
||||
(pb :attempt-5
|
||||
:instrument :fmrhodes1
|
||||
:legato 1
|
||||
:embed :with-lengths-2
|
||||
:embed :maybe-arpegio)
|
||||
;; (play :attempt-5)
|
||||
;; (end :attempt-5)
|
||||
;; (stop :attempt-5)
|
||||
;; this also works, yay!
|
||||
;; now, can I have several :embed arguments?
|
||||
(next-upto-n (pdef :attempt-5) 10)
|
||||
|
||||
;; for some reason :dur shows up in a stream printed form, but same thing plays
|
||||
;; maybe I need :embed in the beginning, so that I would overwrite it?
|
||||
;; nope. I just had (play :attempt-4), so whops, more than a reason to get emacs support package
|
||||
|
||||
;;; It works!
|
||||
;; yay.
|
||||
|
||||
;;; so, next? is trying to set attributes like :legato or :octave
|
||||
;; per tact \ phrase regardless of how many events are there
|
||||
;; maybe #'PMETA , maybe with :stepinject
|
||||
;; nah?
|
||||
;;
|
||||
;; or maybe still arpeggio?
|
||||
;; it would play first pattern until the end, but would also want the pattern of the repeating attribute to end
|
||||
;; right?
|
||||
;; I guess maybe as there are limits for "amount of events from stream"
|
||||
;; there could be limits for "amount of clock ticks / beats"?
|
||||
;; yup, pfindur
|
||||
|
||||
(pdef :with-with-beat-limiting (pfindur (pbind :eitght-beat-limiting t) 8))
|
||||
(pb :test-limiting
|
||||
:embed :with-with-beat-limiting
|
||||
:dur 1/4
|
||||
:degree (pwhite 0 7))
|
||||
(next-upto-n (pdef :test-limiting) 30)
|
||||
|
||||
;; nah, what do I really want?
|
||||
;; let's take the arpeggio as it is,
|
||||
;; but then to 2 tacts of 1 beat per event,
|
||||
;; and then 2 tacks of 1/4
|
||||
|
||||
(pb :try-arpeggio-with-durs
|
||||
:embed :maybe-arpegio
|
||||
)
|
||||
;; (play :try-arpeggio-with-durs)
|
||||
;; (end :try-arpeggio-with-durs)
|
||||
;; (stop :try-arpeggio-with-durs)
|
||||
|
||||
(pbind
|
||||
:dur (pseq (list 1 1/4)))
|
||||
;; now that maybe done with arpeggio?
|
||||
;; (next-upto-n (pdef :try-per-tact-with-parp) 20)
|
||||
(next-upto-n (parp
|
||||
(pbind :dur (pseq (list 1 1/2)))
|
||||
(pfindur (pr (pk :dur)) 4)) 30)
|
||||
;; oh, wow, yea
|
||||
(pdef :durations-per-tact
|
||||
(parp
|
||||
(pbind :value (pseq (list 1 1/2)))
|
||||
(pfindur (pr (pk :value)) 4)))
|
||||
(next-upto-n (pdef :durations-per-tact) 30)
|
||||
|
||||
(pb :try-arpeggio-with-durations-per-tact
|
||||
:instrument :fmrhodes1
|
||||
:embed :maybe-arpegio
|
||||
:dur (pdef :durations-per-tact)
|
||||
;; :embed :durations-per-tact
|
||||
)
|
||||
(next-upto-n (pdef :try-arpeggio-with-durations-per-tact) 40)
|
||||
;; (play :try-arpeggio-with-durations-per-tact)
|
||||
;; (stop :try-arpeggio-with-durations-per-tact)
|
||||
;; (end :try-arpeggio-with-durations-per-tact)
|
||||
|
||||
;; so, this is almost what I want?
|
||||
;; with durations I'd likely want either something different, or make sure
|
||||
;; that phrases can be sped up to the multiple
|
||||
;;
|
||||
;; but that's exactly what I want for legato?
|
||||
|
||||
(pb :try-arpeggio-with-legato-per-tact
|
||||
:instrument :fmrhodes1
|
||||
:embed :maybe-arpegio
|
||||
:legato (pdef :durations-per-tact)
|
||||
;; :embed :legato-per-tact
|
||||
)
|
||||
(next-upto-n (pdef :try-arpeggio-with-legato-per-tact) 40)
|
||||
;; (play :try-arpeggio-with-legato-per-tact)
|
||||
;; (stop :try-arpeggio-with-legato-per-tact)
|
||||
;; (end :try-arpeggio-with-legato-per-tact)
|
||||
;; oh no that's not it!
|
||||
;; :durations-per-tact don't actually look at :dur of the final stream
|
||||
;; but produce static
|
||||
;; (1 1 1 1 1/2 1/2 1/2 1/2 1/2 1/2 1/2 1/2 1 1 1 1 1/2 1/2 1/2 1/2 1/2 1/2 1/2
|
||||
;; 1/2 1 1 1 1 1/2 1/2)
|
||||
;; stream. whlp.
|
||||
|
||||
;; so, what if that would be for any other type of attribute, not for duration
|
||||
;; then I could use pbind :dur (pk :dur) I guess,
|
||||
;; and then pfindur would use duration of the embedding stream?
|
||||
|
||||
(pdef :try-keep-attribute-per-tact
|
||||
(parp
|
||||
(pbind :value (pseq (list 1 1/2)))
|
||||
(pbind :dur (pfindur (pr (pk :dur)) 4))))
|
||||
(next-upto-n (pdef :try-keep-attribute-per-tact) 30)
|
||||
;; i think I just need to (pfindur (pr ...) 4)
|
||||
;; but that's for single value
|
||||
;; so if I'm keeping it too simple for stupid first step:
|
||||
(pdef :abc-per-tact
|
||||
(pseq (list
|
||||
(pfindur (pbind :attr "a" :dur (pk :dur)) 4)
|
||||
(pfindur (pbind :attr "b" :dur (pk :dur)) 4)
|
||||
(pfindur (pbind :attr "c" :dur (pk :dur)) 4))
|
||||
))
|
||||
(next-upto-n (pdef :abc-per-tact) 30)
|
||||
;; so right now this has default :dur of 1,
|
||||
;; but if I :embed this into a stream with variable
|
||||
|
||||
(pb :trying-abc-with-different-durations
|
||||
:dur 1/2
|
||||
:embed :abc-per-tact)
|
||||
(next-upto-n (pdef :trying-abc-with-different-durations) 30)
|
||||
;; yep, that seems to work
|
||||
|
||||
;; now I want to not hardcode :attr, and possibly not hardcode 4
|
||||
;; I don't know whether I can use actual :dur
|
||||
|
||||
(pb :trying-abc-with-different-durations-2
|
||||
:dur (pseq (list (pfindur 1 4) (pfindur 1/2 4)))
|
||||
:embed :abc-per-tact
|
||||
)
|
||||
(next-upto-n (pdef :trying-abc-with-different-durations-2) 30)
|
||||
;; yep, that seems to work too
|
||||
|
||||
;; so I could probably define that :attr-per-duration with a marco
|
||||
;; but is there a way to defite it with a fucntion?
|
||||
|
||||
|
||||
|
||||
;;; also, let's make our arpeggio aligned by 2 tacts in 4 measure, so 8 beats?
|
||||
;; there was something that aligns with padding pauses in the end?
|
||||
|
||||
(pdef :maybe-arpegio-padded
|
||||
(parp (pbind :chord (pseq (list :minor-triad :major) 2))
|
||||
;; (pbind :note (psync (pseq (pnary #'nchord (pk :chord)) 2) 8))
|
||||
(psync (pbind :note (pseq (pnary #'nchord (pk :chord)) 2)) 4)))
|
||||
;; (play :maybe-arpegio-padded)
|
||||
;; (end :maybe-arpegio-padded)
|
||||
;; (stop :maybe-arpegio-padded)
|
||||
(next-upto-n (pdef :maybe-arpegio-padded) 30)
|
||||
|
||||
;; (next-upto-n (psync (pseq (list 1 2 3) 6) 8) 30) ;; maybe that doesn't work because #'PSYNC need to be in context of bound stream, with :dur present?
|
||||
;; that's possible
|
||||
|
||||
(next-upto-n (psync (pbind
|
||||
:attr (pseq (list 1 2 3) 6)
|
||||
:dur 1) 8) 30)
|
||||
;; yup, thats it
|
||||
|
||||
;; so. ugh. if I have arpeggio.
|
||||
;; then how do I add padding? possibly around the whole thing?
|
||||
;; but then I'm loosing information about each particular chord
|
||||
|
||||
;;; well, now I have arpegios psync'ed to 8 beats \ 2 tacts
|
||||
;; so I could try to do per tact legato
|
||||
|
||||
(pdef :legato-per-tact
|
||||
(pseq (list
|
||||
(pfindur (pbind :legato 1 :dur (pk :dur)) 8)
|
||||
(pfindur (pbind :legato 0.7 :dur (pk :dur)) 8)
|
||||
(pfindur (pbind :legato 0.2 :dur (pk :dur)) 8))
|
||||
))
|
||||
(next-upto-n (pdef :legato-per-tact) 30)
|
||||
|
||||
(pb :arpegio-synced-and-per-tact-legato
|
||||
:embed :maybe-arpegio-padded
|
||||
:embed :legato-per-tact)
|
||||
;; (play :arpegio-synced-and-per-tact-legato)
|
||||
;; (stop :arpegio-synced-and-per-tact-legato)
|
||||
(next-upto-n (pdef :arpegio-synced-and-per-tact-legato) 30)
|
||||
|
||||
;;; that is kind of a solution
|
||||
;; and likely mapping patterns is a thing, so I could have
|
||||
|
||||
;; now, let's try overwriting duration?
|
||||
|
||||
|
||||
;;; well, current padding is still "outside" of pseq that is limited to 2 repetitions.
|
||||
;; so, I'd want psync somehow inside of pseq?
|
||||
|
||||
;; arpegiator is like this
|
||||
(next-upto-n (pseq (list 0 1 2 3) 2) 30)
|
||||
;; but I want it to be 0 1 2 3 .... repeated as many times as needed to be inside of 8 beats, and padded with pauses
|
||||
|
||||
|
||||
(next-upto-n (psync (pbind :degree (pseq (list 0 1 2 3))) 8 8 ) 30)
|
||||
;; nope.
|
||||
;; well, i guess maybe it's here where I'd need pmeta?
|
||||
|
||||
|
||||
(pdef :maybe-arpegio-padded-2
|
||||
(parp (pbind :chord (pseq (list :minor-triad :major) 2))
|
||||
;; (pbind :note (psync (pseq (pnary #'nchord (pk :chord)) 2) 8))
|
||||
(psync (pbind :note (pseq (pnary #'nchord (pk :chord)))) 8 8)))
|
||||
;; (play :maybe-arpegio-padded-2)
|
||||
;; (end :maybe-arpegio-padded-2)
|
||||
;; (stop :maybe-arpegio-padded-2)
|
||||
(next-upto-n (pdef :maybe-arpegio-padded-2) 30)
|
||||
|
||||
;; or maybe I need to make pseq repeat 1 time
|
||||
;; and then wrap that in repeat, and then do psync over that?
|
||||
|
||||
(next-upto-n (psync (pn (pbind :degree (pseq (list 0 1 2) 1))) 8 8 ) 30)
|
||||
;; pr - repeats each event - so 0 1 2 repeated once
|
||||
;; pn - loops source pattern - so 0 1 2 0 1 2 0 1 | psynced here
|
||||
;; because psync still considers per single event
|
||||
|
||||
;;; so the question is:
|
||||
;; how can I write a pseq and have it repeating for duration,
|
||||
;; taking into account durations of notes that can be set in the outer stream
|
||||
;; so that repeat would end on a final note and padded rest with pause, not breaking last loop?
|
||||
|
||||
;;; well, while I don't know the answer, let's work with "per phrase legato"
|
||||
;; just have 'breaking last loop iteration' repeat
|
||||
;; and play around with durations
|
||||
|
||||
(pb :lets-vary-durations-in-arpegio-with-phrase-legato
|
||||
:instrument :fmrhodes1
|
||||
:octave 3
|
||||
:embed :maybe-arpegio-padded-2
|
||||
:embed :legato-per-tact
|
||||
:dur 1/3
|
||||
)
|
||||
;; (play :lets-vary-durations-in-arpegio-with-phrase-legato)
|
||||
;; (end :lets-vary-durations-in-arpegio-with-phrase-legato)
|
||||
;; (stop :lets-vary-durations-in-arpegio-with-phrase-legato)
|
||||
|
||||
;; during the playthrough setting :dur to different 1 1/2 1/3 1/6, that's nice
|
||||
|
||||
|
||||
;;; now let's copy things over so that all components are close together:
|
||||
|
||||
;; exhibit A
|
||||
(defun not-perfect-but-arpeggio (chords &optional (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)))) phrase-dur phrase-dur)))
|
||||
(pdef :maybe-arpegio-padded-3 (not-perfect-but-arpeggio (list :major :minor)))
|
||||
;; (play :maybe-arpegio-padded-3)
|
||||
;; (end :maybe-arpegio-padded-3)
|
||||
;; (stop :maybe-arpegio-padded-3)
|
||||
;; (next-upto-n (pdef :maybe-arpegio-padded-3))
|
||||
;; (next-upto-n (pdef (not-perfect-but-arpeggio (list :major :minor))) 30)
|
||||
;; (next-upto-n (not-perfect-but-arpeggio (list :major :minor)) 30)
|
||||
;; (next-upto-n (not-perfect-but-arpeggio (list :major :minor :minor-6th)) 30)
|
||||
|
||||
;; so to have patterns with arguments
|
||||
;; I just need to return the pattern - pbind or another constructor from the function
|
||||
;; and then bind it to the name with pdef, or just pass in to #NEXT-UPTO-N or to key in #'PB (likely, right?)
|
||||
|
||||
;; can I do same thing with legato per phrase?
|
||||
(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)))
|
||||
(attr-per-phrase :legato (list 1 0.7 0.2))
|
||||
;; #<PSEQ (#<PFINDUR (PBIND :LEGATO 1 :DUR #<PK :DUR 1>) 8 0>
|
||||
;; #<PFINDUR (PBIND :LEGATO 0.7 :DUR #<PK :DUR 1>) 8 0>
|
||||
;; #<PFINDUR (PBIND :LEGATO 0.2 :DUR #<PK :DUR 1>) 8 0>) :INF 0>
|
||||
;; wowy, is that what I think it is?
|
||||
|
||||
(pb :lets-have-arpeggio-with-phrase-settings-and-vary-other-things-manually
|
||||
:embed (not-perfect-but-arpeggio (list :major :minor :minor-6th :minor-7th :major-7th :major)) ; each chord plays arpeggio for whole phrase
|
||||
:embed (attr-per-phrase :legato (list 1 0.7 0.2 0.8)) ; each phrase takes single value for legato
|
||||
; even if amount of events in phrase change with change of :dur
|
||||
:dur 1/3
|
||||
)
|
||||
;; (play :lets-have-arpeggio-with-phrase-settings-and-vary-other-things-manually)
|
||||
;; (end :lets-have-arpeggio-with-phrase-settings-and-vary-other-things-manually)
|
||||
;; (stop :lets-have-arpeggio-with-phrase-settings-and-vary-other-things-manually)
|
||||
|
||||
;; and now I'm limited by my understanding of chords and how to select progressions
|
||||
;; also - the base for the chord! currently we only select root
|
||||
;; it's maybe not as clean as have root coupled with the chord, but could add attr-per-phrase with root seleciton, that could work?
|
||||
;; but! the root is in "note" mode or "degree" mode?
|
||||
(pb :is-root-degree-or-note
|
||||
:degree 0
|
||||
:root (pseq (list 0 1 2 3 4 5 6 7) 1))
|
||||
;; (play :is-root-degree-or-note)
|
||||
;; (end :is-root-degree-or-note)
|
||||
;; definitely degree, right?
|
||||
|
||||
;; so let's do arpegios for some of the chord progressions I had as whole chords?
|
||||
;; i - III - iv - VI
|
||||
(pb :lets-arpegio-i-III-iv-VI
|
||||
:embed (not-perfect-but-arpeggio (list :minor :major :minor :major)) ; each chord plays arpeggio for whole phrase
|
||||
:embed (attr-per-phrase :legato (list 1 0.7 0.2 0.8)) ; 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 0 2 3 5))
|
||||
:dur 1/4
|
||||
)
|
||||
;; (play :lets-arpegio-i-III-iv-VI)
|
||||
;; (end :lets-arpegio-i-III-iv-VI)
|
||||
;; (stop :lets-arpegio-i-III-iv-VI)
|
||||
|
||||
;; IV V iii vi
|
||||
(pb :lets-arpegio-IV-V-iii-vi
|
||||
:embed (not-perfect-but-arpeggio (list :major :major :minor :minor)) ; each chord plays arpeggio for whole phrase
|
||||
:embed (attr-per-phrase :legato (list 1 0.7 0.2 0.8)) ; 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 2 5))
|
||||
:dur 1
|
||||
)
|
||||
;; (play :lets-arpegio-IV-V-iii-vi)
|
||||
;; (end :lets-arpegio-IV-V-iii-vi)
|
||||
;; (stop :lets-arpegio-IV-V-iii-vi)
|
||||
|
||||
;;; now, if I want a simple pase line?
|
||||
;;; like taking a chord and holding it, or playing whole with simle pattern?
|
||||
(next-upto-n (pdef :lets-arpegio-iv-v-iii-vi) 30)
|
||||
;; well, #'not-perfect-but-arpeggio does inject :chord as an attribute
|
||||
;; but if I don't merge this with base line, and only #'PPAR, then base pattern \ stream wouldn't have it
|
||||
;; so, I guess I'd want to have "generic base line" that takes in a list of chords
|
||||
;; and pass in same list (or maybe even a different list sometimes)
|
||||
;; and well, I'd also need to pass in roots for those chords, since right now they are separate, oh well
|
||||
|
||||
(setq *my-chords* (list :major :major :minor :minor))
|
||||
;; (setq *my-chords* (list :major :minor))
|
||||
;; (setq *my-bases* (list 3 4))
|
||||
(setq *my-bases* (list 3 4 2 5))
|
||||
|
||||
;; let's have a phrase that plays chord over base for 4 beats - 2 tacts
|
||||
;; still would need parp, right?
|
||||
(pb :simple-base-line
|
||||
(parp
|
||||
(pbind
|
||||
:chord (pseq *my-chords* 2)
|
||||
:root (pseq *my-bases* 2)
|
||||
)
|
||||
(pbind
|
||||
:note (pnary #'chord-notes (pk :chord))
|
||||
:dur (pseq (list 4 1/2 1/2 (prest 3)) 1)) ; that's 2 tacts
|
||||
))
|
||||
(pb :simple-base
|
||||
:instrument :fmbass
|
||||
:embed :simple-base-line
|
||||
:embed (attr-per-phrase :octave (list 3 2) (* 4 2 4))) ; 4 beats per tact, 2 tacts per chord, 4 hard coded chords
|
||||
|
||||
;; (play :simple-base)
|
||||
;; (end :simple-base)
|
||||
;; (stop :simple-base)
|
||||
|
||||
;; other simpler way would be to make parp - with simple-base-line playing for each :octave
|
||||
|
||||
(next-upto-n (pdef :simple-base) 60)
|
||||
;;; and yes this could also be more configurable, let's just try to combine these first
|
||||
|
||||
;; IV V iii vi - same 3 4 2 5 from :simple-base
|
||||
(pdef :try-one-arpeggio-and-bass
|
||||
(ppar (list (pdef :simple-base) (pdef :lets-arpegio-IV-V-iii-vi))))
|
||||
;; (play :try-one-arpeggio-and-bass)
|
||||
;; (stop :try-one-arpeggio-and-bass)
|
||||
;; (end :try-one-arpeggio-and-bass)
|
||||
|
||||
|
||||
;;; wait, so my arpeggio doesn't keep whole 2 tacts of same chord, oh, sad
|
||||
|
||||
;; IV V iii vi
|
||||
(pb :lets-arpegio-IV-V-iii-vi
|
||||
;; :instrument :strings
|
||||
:embed (not-perfect-but-arpeggio (list :major :major :minor :minor) 1/4) ; each chord plays arpeggio for whole phrase
|
||||
:embed (attr-per-phrase :legato (list 1 0.7 0.2 0.8)) ; 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 2 5))
|
||||
:dur 1/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)
|
||||
|
||||
;; yup, :dur 1 and :dur 1/2 still produce 8 notes for the :chord
|
||||
|
||||
;; exhibit B
|
||||
(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) ; looks like parent :dur here inaccessible
|
||||
:dur dur
|
||||
)
|
||||
phrase-dur phrase-dur)))
|
||||
|
||||
;; and now it's worse, since need to specify durations twice
|
||||
;; but should align with simple bass
|
||||
|
||||
;; same as before
|
||||
;; IV V iii vi - same 3 4 2 5 from :simple-base
|
||||
(pdef :try-one-arpeggio-and-bass
|
||||
(ppar (list (pdef :simple-base) (pdef :lets-arpegio-IV-V-iii-vi))))
|
||||
;; (play :try-one-arpeggio-and-bass)
|
||||
;; (stop :try-one-arpeggio-and-bass)
|
||||
;; (end :try-one-arpeggio-and-bass)
|
||||
|
||||
;;; let's try updating and rendering again?
|
||||
;; (render (pdef :try-one-arpeggio-and-bass) "/tmp/arpeggio-and-bass-1.wav" :dur 16)
|
||||
;; 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/arpeggio-and-bass.aiff" :leave-open-p t)
|
||||
|
||||
;; ;; now play whatever sounds you like
|
||||
|
||||
;; ;; e.g.
|
||||
;; (in-package :cl-patterns)
|
||||
;; (play :try-one-arpeggio-and-bass)
|
||||
;; (stop :try-one-arpeggio-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
|
||||
176
dirty-journal/2022-09-09-maybe-cleanup-bass-from-chords.lisp
Normal file
176
dirty-journal/2022-09-09-maybe-cleanup-bass-from-chords.lisp
Normal file
@@ -0,0 +1,176 @@
|
||||
(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
|
||||
232
dirty-journal/2022-09-11-attempting-more-with-arpegios.lisp
Normal file
232
dirty-journal/2022-09-11-attempting-more-with-arpegios.lisp
Normal file
@@ -0,0 +1,232 @@
|
||||
;;; today I'd like to do bass arpegios, with high chords
|
||||
;; and maybe drums for both parts (from 09-09)
|
||||
;; and join them?
|
||||
|
||||
;; IV V iii vi
|
||||
;; (setq *my-chords* (list :major :major :minor :minor)
|
||||
;; *my-roots* (list 3 4 2 5))
|
||||
;; (setq *my-chords* (list :major)
|
||||
;; *my-roots* (list 3))
|
||||
|
||||
;; Am – F – C – G (i – VI – III – VII)
|
||||
;; (setq *my-chords* (list :minor :major :major :major)
|
||||
;; *my-roots* (list 0 3 2 6))
|
||||
|
||||
;; i - III - iv - VI
|
||||
(setq *my-chords* (list :minor :major :minor :major)
|
||||
*my-roots* (list 0 2 3 5))
|
||||
|
||||
(in-package :cl-patterns)
|
||||
|
||||
(start-clock-loop :tempo 90/60 :force t)
|
||||
|
||||
(pb :lets-slow-bass-arpegio
|
||||
:dur 2
|
||||
:octave 3
|
||||
;; :instrument :fmbass
|
||||
:embed (not-perfect-but-arpeggio *my-chords*)
|
||||
:embed (attr-per-phrase :root *my-roots*)
|
||||
)
|
||||
;; (play :lets-slow-bass-arpegio)
|
||||
;; (stop :lets-slow-bass-arpegio)
|
||||
|
||||
;; well, what if I rather take my simple-bass thing
|
||||
;; and give it some kind of slow pattern
|
||||
;; nope, that simple-bass plays whole chords
|
||||
;;
|
||||
;; at this point I'm just tempted to not use chords,
|
||||
;; and have a PARP
|
||||
(pdef :chord-defs
|
||||
(pbind :chord (pseq *my-chords* 1)
|
||||
:chord-base (pseq *my-roots* 1)))
|
||||
|
||||
(pb :lets-slow-bass-melody
|
||||
(parp
|
||||
(pdef :chord-defs)
|
||||
(pbind :step (pseq (list 0 1 0 1 2 0 1 2) 1)
|
||||
:dur (pseq (list 1/4 1/4 1 1 1 1 1 5/2) 1)
|
||||
;; :note (pfunc (lambda ()
|
||||
;; (event-value *event* :step)))
|
||||
:note (pfunc (lambda ()
|
||||
(+ (event-value *event* :chord-base)
|
||||
(nth (event-value *event* :step)
|
||||
(chord-notes (event-value *event* :chord))))))
|
||||
)))
|
||||
;; (next-upto-n (pdef :lets-slow-bass-melody) 10)
|
||||
;; (play :lets-slow-bass-melody)
|
||||
;; (end :lets-slow-bass-melody)
|
||||
;; (stop :lets-slow-bass-melody)
|
||||
|
||||
(pb :embedding-bass-melogy-into-pattern
|
||||
(pseq (list (pbind
|
||||
:quant 4
|
||||
:dur (pseq (list (prest 7/2)) 1))
|
||||
(pbind
|
||||
:octave 2 ; let's add these later? when join both?
|
||||
:instrument :fmbass
|
||||
:embed :lets-slow-bass-melody))
|
||||
1))
|
||||
(next-upto-n (pdef :embedding-bass-melogy-into-pattern) 20)
|
||||
;; (play :embedding-bass-melogy-into-pattern)
|
||||
;; (stop :embedding-bass-melogy-into-pattern)
|
||||
;; (end :embedding-bass-melogy-into-pattern)
|
||||
|
||||
;; now. let's brainstorm the pattern on a single chord?
|
||||
|
||||
;; and well, my guess is that pattern should start from 1/2 before tha bar start?
|
||||
|
||||
;; so is there a "timer shift" for pattern?
|
||||
;; if I can only align by quant
|
||||
;; ( upbeat ? )
|
||||
;; well 3 6 9 - and we have -1 +2 and +1 over the quant :4
|
||||
|
||||
;; ok, let's for not simulate that stuff by writing continuous bass melody
|
||||
;; and adding 3 1/2 rest in the beginning
|
||||
|
||||
;; I'd like to add bottom note repeating at 1/2 ?
|
||||
|
||||
;;; let's just do same? quant 4, wait for the upbeat of next bar
|
||||
;;; and start playing 1/2 8 times?
|
||||
(pb :lets-slow-bass-melody-root-repeating
|
||||
(pseq (list (pbind :dur (pseq (list (prest 4)) 1)
|
||||
:quant 4)
|
||||
(parp
|
||||
(pdef :chord-defs)
|
||||
(pbind
|
||||
:octave 1
|
||||
:instrument :fmbass
|
||||
:dur (pseq (list (prest 5/2) (pfindur 1/2 7/2) (prest 2)) 1)
|
||||
:legato 0.5
|
||||
:note (pk :chord-base)))
|
||||
(pbind :dur (pseq (list (prest 1)) 1)))
|
||||
1))
|
||||
(next-upto-n (pdef :lets-slow-bass-melody-root-repeating) 20)
|
||||
;; (play :lets-slow-bass-melody-root-repeating)
|
||||
;; (end :lets-slow-bass-melody-root-repeating)
|
||||
;; (stop :lets-slow-bass-melody-root-repeating)
|
||||
|
||||
(pdef :full-bass-melody
|
||||
(ppar (list :embedding-bass-melogy-into-pattern :lets-slow-bass-melody-root-repeating)))
|
||||
;; (play :full-bass-melody)
|
||||
;; (stop :full-bass-melody)
|
||||
|
||||
;; yay, not sure whether I want :octave 1 or 2, but overall, cool,
|
||||
;; even though - so much still to learn to not have to do manual calculaitons of prest and such
|
||||
|
||||
;; let's have some kind of light chord holding. not sure what I want, maybe default
|
||||
;; maybe strings? or pluck
|
||||
|
||||
(pb :high-chords-hold
|
||||
:embed :chord-defs
|
||||
:instrument :tone-buzz
|
||||
:dur 8
|
||||
:quant 4
|
||||
:amp 0.05
|
||||
:note (p+ (pk :chord-base) (pnary #'chord-notes (pk :chord))))
|
||||
(next-upto-n (pdef :high-chords-hold) 30)
|
||||
;; (play :high-chords-hold)
|
||||
;; (end :high-chords-hold)
|
||||
;; (stop :high-chords-hold)
|
||||
|
||||
(pb :high-chords-with-pre-bar
|
||||
(pseq (list
|
||||
(pbind :dur (pseq (list (prest 4)) 1)) ; most awkward thing
|
||||
(pdef :high-chords-hold))
|
||||
1))
|
||||
|
||||
(pdef :total-base-section
|
||||
(ppar (list :full-bass-melody :high-chords-with-pre-bar)))
|
||||
;; (play :total-base-section)
|
||||
;; (stop :total-base-section)
|
||||
|
||||
;; well, it seems that with restarts defsynts of fmbass start playing worse?
|
||||
;; responding less and less to short notes and legato?
|
||||
;; is that due to not restarting sbcl?
|
||||
;; let's try full restart
|
||||
|
||||
;;; I've done full restart, didn't totally help.
|
||||
;; and I've set slower clock speed
|
||||
|
||||
;;; now, let's add intro, connection and ending?
|
||||
|
||||
(pb :intro
|
||||
:embed :chord-defs
|
||||
:dur (pseq (list 2 2 4) 1)
|
||||
:instrument :strings
|
||||
:amp 0.1
|
||||
:note (p+ (first *my-roots*) (pnary #'chord-notes (first *my-chords*))))
|
||||
;; (play :intro)
|
||||
;; (stop :intro)
|
||||
;; (end :intro)
|
||||
;; idea for not now - third chord make in two octaves?
|
||||
|
||||
;;; maybe add a scratch inbetween?
|
||||
(pb :phrase-connection
|
||||
:instrument :fmbass
|
||||
:dur (pseq (list (prest 2) 12 (prest 4)) 1)
|
||||
:embed :chord-defs
|
||||
:octave 2
|
||||
:note (p+ (first *my-roots*) (pnary #'chord-notes (first *my-chords*)))
|
||||
)
|
||||
;; (play :phrase-connection)
|
||||
;; (stop :phrase-connection)
|
||||
|
||||
;;; for this to work, also evaluate ~/Documents/personal/common-lisp-study/music/dirty-journal/2022-09-09-maybe-cleanup-bass-from-chords.lisp
|
||||
;; maybe later on cleanup I'd put everything into same file
|
||||
|
||||
(pdef :is-that-first-experiment
|
||||
(pseq (list (pdef :intro)
|
||||
(pdef :total-base-section)
|
||||
(pdef :phrase-connection)
|
||||
(pdef :arpegios-and-bass))
|
||||
1))
|
||||
;; (play :is-that-first-experiment)
|
||||
;; (stop :is-that-first-experiment)
|
||||
;; (end :is-that-first-experiment)
|
||||
|
||||
;; welp, when notes are too quick, they are not produced
|
||||
;; and I also kind of wanted a percussion line, but oh well
|
||||
|
||||
;; ;;; ok, let's record that,
|
||||
|
||||
;; ;; 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
|
||||
;; ;; ;; IV V iii vi
|
||||
;; ;; Am – F – C – G (i – VI – III – VII)
|
||||
;; ;; i - III - iv - VI
|
||||
;; (buffer-write mybuffer "/tmp/first-experiment-i-III-iv-VI.aiff" :leave-open-p t)
|
||||
|
||||
;; ;; now play whatever sounds you like
|
||||
|
||||
;; ;; e.g.
|
||||
;; (in-package :cl-patterns)
|
||||
;; (play :is-that-first-experiment)
|
||||
;; (stop :is-that-first-experiment)
|
||||
;; (end :is-that-first-experiment)
|
||||
|
||||
;; ;; 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
|
||||
171
dirty-journal/2022-09-21-trying-new-arpeggios.lisp
Normal file
171
dirty-journal/2022-09-21-trying-new-arpeggios.lisp
Normal file
@@ -0,0 +1,171 @@
|
||||
|
||||
(in-package #:cl-patterns)
|
||||
|
||||
;; i want to get arpeggios of configurable speed
|
||||
;; and configured by chord
|
||||
;; and configured by places of notes in a chord
|
||||
;; let's again first do consecutive notes from a chord
|
||||
;; idea is to have
|
||||
;; a) endless loop of notes from a chord
|
||||
;; b) have pdurstutter - for the duration of desired arpeggio, with maybe figuring out to make each part of stutter into a separate item in arpeggio
|
||||
|
||||
(all-chords)
|
||||
(chord-notes (chord "Minor 7th"))
|
||||
|
||||
(pdef :at-first-chords
|
||||
(pbind :note (pseq (chord-notes (chord "Minor 7th")))))
|
||||
;; (play :at-first-chords)
|
||||
;; (stop :at-first-chords)
|
||||
|
||||
(pdef :initial-stutter
|
||||
(pdurstutter (pbind
|
||||
:dur (pseq (list 4) 1)) 16))
|
||||
;; (play :initial-stutter)
|
||||
;; (end :initial-stutter)
|
||||
;; (stop :initial-stutter)
|
||||
|
||||
(pb :initial-combination
|
||||
;; :embed :initial-stutter
|
||||
;; :arpeggio-chord :minor-6th
|
||||
:dur (pdurstutter (pseq (list 4) 1) 16)
|
||||
:note (pseq (pnary #'chord-notes (pk :arpeggio-chord)))
|
||||
)
|
||||
;; (next-upto-n (pdef :initial-combination) 32)
|
||||
;; (play :initial-combination)
|
||||
;; (end :initial-combination)
|
||||
;; (stop :initial-combination)
|
||||
|
||||
(chord-notes :minor-6th)
|
||||
|
||||
;; now do arpegio pattern to play arpegio per each chord?
|
||||
(pb :with-changing-chords
|
||||
(parp
|
||||
(pbind :arpeggio-chord (pseq (list :minor-6th :minor :minor-7th :minor)))
|
||||
(pdef :initial-combination)))
|
||||
;; (next-upto-n (pdef :with-changing-chords) 40)
|
||||
;; (play :with-changing-chords)
|
||||
;; (stop :with-changing-chords)
|
||||
|
||||
;; that's kind of ok if chords have same amount of notes in it?
|
||||
(mapcar #'chord-notes (list :minor-6th :minor :minor-7th :minor))
|
||||
(chord :major)
|
||||
|
||||
;; would it be better if it's all in single def?
|
||||
(pb :with-changing-chords-2
|
||||
(parp
|
||||
(pbind :arpeggio-chord (pseq (list :major :minor :major :minor) 1)
|
||||
:chord-root (pseq (list 0 3 2 6) 1))
|
||||
(pbind
|
||||
:dur (pdurstutter (pseq (list 4) 1) 24)
|
||||
:note (pseq (p+ (pk :chord-root) (pnary #'chord-notes (pk :arpeggio-chord)))))))
|
||||
;; (play :with-changing-chords-2)
|
||||
;; (end :with-changing-chords-2)
|
||||
|
||||
;; now I could use stats of the :arpeggio-chord in the :dur part
|
||||
;; i guess i'd like to what?
|
||||
;; to be adding root of the chord
|
||||
;; and then pattern to be played over the chord
|
||||
|
||||
;; let's first make simple endless pattern that takes list of steps, and takes them out of chord-notes
|
||||
(pb :initial-patterned
|
||||
:pattern (list 0 1 2 0 3)
|
||||
:note (pnary (lambda (a) (nth a (chord-notes :major-7th))) (pseq (pk :pattern))))
|
||||
(next-upto-n (pdef :initial-patterned) 20)
|
||||
;; (play :initial-patterned)
|
||||
;; (stop :initial-patterned)
|
||||
|
||||
;; and now i want what? i want to do pnary? pfunc
|
||||
|
||||
(pb :with-patterned-changing-chords
|
||||
(parp
|
||||
;;; first part of parp is "base values" for each event whole second pattern will be played
|
||||
;;; so this pattern produces "settings for each phrase"
|
||||
(pbind :arpeggio-chord (pseq (list :minor-6th :minor :minor-7th :minor))
|
||||
:chord-root (pseq (list 0 3 2 6) 1)
|
||||
:pattern (list 0 1 2 1 2 1 2 0))
|
||||
;;; this patten would play our fully with settings values
|
||||
(pbind
|
||||
:note (pnary (lambda (chord-step chord chord-root)
|
||||
(+ chord-root (nth chord-step (chord-notes chord))))
|
||||
(pseq (pk :pattern))
|
||||
(pk :arpeggio-chord)
|
||||
(pk :chord-root))
|
||||
:dur (pdurstutter (pseq (list 8) 1) 32))))
|
||||
;; (next-upto-n (pdef :with-patterned-changing-chords) 30)
|
||||
;; (play :with-patterned-changing-chords)
|
||||
;; (stop :with-patterned-changing-chords)
|
||||
|
||||
;; next I'd probably want to what? somehow align chords that have 3 \ 4 \ 5 notes in them
|
||||
;; not sure what could be done though logically
|
||||
;; we could have different patterns, based on chord size, yup
|
||||
|
||||
(pb :instrumented-play
|
||||
:instrument :fmbass
|
||||
:legato 0.5
|
||||
:octave 2
|
||||
:embed :with-patterned-changing-chords)
|
||||
;; (play :instrumented-play)
|
||||
;; (end :instrumented-play)
|
||||
|
||||
;; i guess next is making this pattern a function that takes patterns to provice chords, roots and pattrn
|
||||
;; then could use embed and set attributes in place
|
||||
;; this is actually fun
|
||||
|
||||
(defun patterned-arpeggio (chords roots patterns &optional (chord-duration 8) (events-in-chord 32))
|
||||
(parp
|
||||
;;; first part of parp is "base values" for each event whole second pattern will be played
|
||||
;;; so this pattern produces "settings for each phrase"
|
||||
(pbind :arpeggio-chord chords
|
||||
:chord-root roots
|
||||
:pattern patterns)
|
||||
;;; this patten would play our fully with settings values
|
||||
(pbind
|
||||
:note (pnary (lambda (chord-step chord chord-root)
|
||||
(+ chord-root (nth chord-step (chord-notes chord))))
|
||||
(pseq (pk :pattern))
|
||||
(pk :arpeggio-chord)
|
||||
(pk :chord-root))
|
||||
:dur (pdurstutter (pseq (list chord-duration) 1) events-in-chord))))
|
||||
|
||||
(pb :first-try-of-function
|
||||
:instrument :fmbass
|
||||
:legato 0.5
|
||||
:octave 2
|
||||
:embed (patterned-arpeggio
|
||||
(pseq (list :minor-6th :minor :minor-7th :minor))
|
||||
(pseq (list 0 3 2 6) 1)
|
||||
(list 0 1 2 1 2 1 2 0)))
|
||||
;; (play :first-try-of-function)
|
||||
;; (end :first-try-of-function)
|
||||
|
||||
;; taking progressions from
|
||||
;; https://en.wikipedia.org/wiki/List_of_chord_progressions
|
||||
|
||||
(pb :second-try-of-function
|
||||
:instrument :fmbass
|
||||
:legato 0.5
|
||||
:octave 2
|
||||
:embed (patterned-arpeggio
|
||||
(pseq (list :major :minor :major :major))
|
||||
(pseq (list 0 5 3 4) 1)
|
||||
(list 0 1 2 1 2 1 2 0)
|
||||
2 8))
|
||||
;; (play :second-try-of-function)
|
||||
;; (end :second-try-of-function)
|
||||
|
||||
;; andalusian cadence iv-III-II-I
|
||||
(pb :third-try-of-function
|
||||
;; :instrument :fmbass
|
||||
;; :instrument :strings
|
||||
:instrument :prophet5pwmstrings
|
||||
:legato 1
|
||||
:octave 5
|
||||
:embed (patterned-arpeggio
|
||||
(pseq (list :minor :major :major :major))
|
||||
(pseq (list 3 2 1 0) 1)
|
||||
(list 0 1 2 1 2 1 2 0)
|
||||
;; 2 16
|
||||
8 16
|
||||
))
|
||||
;; (play :third-try-of-function)
|
||||
;; (stop :third-try-of-function)
|
||||
@@ -290,10 +290,6 @@ with fixed synthdefs
|
||||
** tried synths in a pattern and they work!
|
||||
even though they don't stop on their own,
|
||||
so maybe `gate` is a default argument that passes control from the pattern system, using `dur`
|
||||
** NEXT - learn more about puttin melodies in, midinotes and stuff
|
||||
what I want is "pitch model"
|
||||
http://doc.sccode.org/Tutorials/Streams-Patterns-Events5.html
|
||||
** NEXT - how to keep same note pattern repeating with different settings of legato \ duration
|
||||
* [2022-09-04 Sun]
|
||||
** evil marcro for wrapping consecutive values (or args) into pairwise brackets:
|
||||
well, not being inserted due to backspace, sad
|
||||
@@ -318,3 +314,117 @@ Example:
|
||||
|
||||
is that pause?
|
||||
but why would event then still have :DEGREE attribute?
|
||||
* [2022-09-05 Mon]
|
||||
** let's what? move instruments into separate organized files?
|
||||
meh, let's try for arpeggio from chords?
|
||||
or something
|
||||
** DONE - learn more about puttin melodies in, midinotes and stuff
|
||||
what I want is "pitch model"
|
||||
http://doc.sccode.org/Tutorials/Streams-Patterns-Events5.html
|
||||
:degree - is from an octave, and :octave 5 default and quite high, :root is which octave to take
|
||||
** DONE - how to keep same note pattern repeating with different settings of legato \ duration
|
||||
I'll try to define notes separately with pdef and insert it? would then single length would be for all?
|
||||
** so, I tried to figure out how to change parameters for whole "phrases"
|
||||
"automatic jazz" does that with getting new random value, that gets repeated "forever" until the end of the pattern
|
||||
|
||||
if I try to use not random, but "from sequence", then on pattern restart I'd get first element of the sequence every time.
|
||||
|
||||
so then "kind of working" solution, is keep melogy repeating,
|
||||
then - know what is the length of the melody and repeat for "amount of events" in the melody,
|
||||
* [2022-09-08 Thu]
|
||||
** one day I'll move all instruments into easy to evaluate \ import \ use package
|
||||
but not today? because I don't yet too comfortable with the concept of Common-Lisp packages
|
||||
** and today?
|
||||
*** TODO get more code on creating arpeggios by specifying chords
|
||||
not quite, but yeah
|
||||
*** DONE and maybe how to combine \ merge \ include patterns
|
||||
so that chord pattern is defined separately and merged into separate patterns for base \ melogy
|
||||
|
||||
one convenient way to do it is to use :embed key in the pdef
|
||||
#+begin_src common-lisp
|
||||
(pb :with-lengths-2
|
||||
:dur 2)
|
||||
(pb :attempt-5
|
||||
:instrument :fmrhodes1
|
||||
:legato 1
|
||||
:embed :with-lengths-2)
|
||||
(next-upto-n (pdef :attempt-5) 10)
|
||||
#+end_src
|
||||
|
||||
and there can be several :embed's yay
|
||||
|
||||
another pay is #'PCHAIN
|
||||
judging by documentation it's very similar, not sure when it would be more convenient
|
||||
#+begin_src common-lisp
|
||||
(pdef :attempt-3
|
||||
(pchain (pdef :legato-keys) (pdef :maybe-arpegio)))
|
||||
(next-upto-n (pdef :attempt-3) 10)
|
||||
#+end_src
|
||||
|
||||
*** DONE also - maybe I'd learn about setting parameters "per tact" and not "per event"
|
||||
- I already guess that it would be infinitely repeating pattern that somehow aligns by beat number, maybe?
|
||||
then we'd get emitting for example :legato for each event in a tact regardless of it being 1 or 1/16s
|
||||
|
||||
I think something similar I saw at #'PMETA, like connecting patterns with some kind of measuring
|
||||
|
||||
kind of have some kind of solution here
|
||||
** so what was going on today:
|
||||
*** :embed - in pb
|
||||
if I have separate stream \ patter with some of the values
|
||||
I can "include" it into currently defined stream.
|
||||
so for example notes and durations are saved under :melody-pattern
|
||||
|
||||
and other patterns embed it and specify own :instrument and :octave
|
||||
[[file:2022-09-08-more-on-chord-melodies.lisp::(pb :attempt-5]]
|
||||
*** trying "attribute per tact" - with PARP - arpegio
|
||||
**** starting with durations per tact:
|
||||
[[file:2022-09-08-more-on-chord-melodies.lisp::(pdef :durations-per-tact]]
|
||||
|
||||
not quite
|
||||
|
||||
**** then attribute per tact:
|
||||
[[file:2022-09-08-more-on-chord-melodies.lisp::(pdef :abc-per-tact]]
|
||||
**** the simplest hardcoded version
|
||||
and with :legato
|
||||
[[file:2022-09-08-more-on-chord-melodies.lisp::(pdef :legato-per-tact]]
|
||||
|
||||
**** to probably what I want?
|
||||
[[file:2022-09-08-more-on-chord-melodies.lisp::defun attr-per-phrase (attr-name values &optional (phrase-dur 8)]]
|
||||
*** also wanted to "pad" arpeggio, so that it would fill full two tacts, but only have complete loop iterations
|
||||
in that I didn't succeed
|
||||
having PSYNC around PSEQ - inner pattern started last incomplete iteration instead of producing rest
|
||||
**** initial implementation also didn't fill two tacts
|
||||
[[file:2022-09-08-more-on-chord-melodies.lisp::defun not-perfect-but-arpeggio (chords &optional (phrase-dur 8)]]
|
||||
in it the #'PSYNC didn't really work because it was around pattern that didn't have :dur
|
||||
**** next iteration that starts unfinished last loops
|
||||
[[file:2022-09-08-more-on-chord-melodies.lisp::defun not-perfect-but-arpeggio (chords &optional (dur 1) (phrase-dur 8)]]
|
||||
|
||||
but I have to pass in :dur,
|
||||
so in pattern I currently have to change it in two places.
|
||||
seems that "parent" pattern is inaccessible with (pk :dur)
|
||||
|
||||
- note: I somewhere read phrase "parent pattern", so possibly in some #'PFUNC or #'PNARY
|
||||
maybe I could access attributes of a pattern that :embed this one
|
||||
** what I want next - clean up defsynths, clean up arpegio thing, bass thing
|
||||
maybe put everything under "dirty-journal" directory
|
||||
and start a "clean" journal
|
||||
* [2022-09-09 Fri]
|
||||
** let's move everything into "dirty-journal"
|
||||
* [2022-09-11 Sun]
|
||||
** so, today I've been writing bass arpeggios
|
||||
** biggest questin - upbeat before first bar,
|
||||
how to effectively write that?
|
||||
|
||||
so that it would be easy to sync things on :quant
|
||||
** thing I found out -
|
||||
it would be nice to specify chords and chord-bases as a pattern
|
||||
to be embedded
|
||||
|
||||
that way I'd be able to switch it up on the go and all patterns extending it would pick it up?
|
||||
well, maybe not all at the same time, if they are not synched =C
|
||||
** would be nice to put everything of 09-09 and 09-11 into single file
|
||||
to make it easier to restart whole first experiment with different chords
|
||||
|
||||
also, have I saved a link to the side where I saw the chord progressions I used?
|
||||
|
||||
also-also having a keyboard could be a nice help
|
||||
4
stabler-things/functions.lisp
Normal file
4
stabler-things/functions.lisp
Normal file
@@ -0,0 +1,4 @@
|
||||
(in-package :cl-patterns)
|
||||
(defun nchord (symbol &optional (base 0))
|
||||
"Return list of notes for chord names by SYMBOL over the BASE."
|
||||
(mapcar (lambda (note) (+ base note)) (chord-notes (chord symbol))))
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
;; https://defaultxr.github.io/cl-collider-tutorial/02-getting-started.html
|
||||
|
||||
(ql:quickload :cl-collider)
|
||||
@@ -8,6 +7,7 @@
|
||||
(server-boot *s*) ; already in use
|
||||
|
||||
|
||||
(ql:quickload :cl-patterns)
|
||||
(ql:quickload :cl-patterns/supercollider)
|
||||
|
||||
;; ...this will take care of loading cl-collider for you if it's not already loaded.
|
||||
170
stabler-things/synthesizers.lisp
Normal file
170
stabler-things/synthesizers.lisp
Normal file
@@ -0,0 +1,170 @@
|
||||
(in-package #:cl-collider)
|
||||
|
||||
;;; keys
|
||||
|
||||
(defsynth FMRhodes1 ((out 0) (freq 440) (gate 1) (pan 0) (amp 0.1) (att 0.001) (rel 1) (lfoSpeed 4.8) (inputLevel 0.2)
|
||||
(modIndex 0.2) (mix 0.2) (lfoDepth 0.1)) ;; all of these range from 0 to 1
|
||||
(let* ((env1 (env-gen.kr (perc att (* rel 1.25) inputLevel :lin)))
|
||||
(env2 (env-gen.kr (perc att rel inputLevel :lin)))
|
||||
(env3 (env-gen.kr (perc att (* rel 1.25) inputLevel :lin)))
|
||||
(env4 (env-gen.kr (perc att (* rel 1.25) inputLevel :lin)))
|
||||
(osc4 (* (sin-osc.ar freq) 6.7341546494171 modIndex env4))
|
||||
(osc3 (* (sin-osc.ar (* freq 2) osc4) env3))
|
||||
(osc2 (* (sin-osc.ar (* freq 30)) 0.683729941 env2))
|
||||
(osc1 (* (sin-osc.ar (* freq 2)) env1))
|
||||
(snd-step-1 (+ (mix (* osc3 (- 1 mix))) (* osc1 mix)))
|
||||
(snd-step-2 (* snd-step-1 (range (sin-osc.ar lfoSpeed) (- 1 lfoDepth) 1)))
|
||||
(snd-step-3 (* snd-step-2 (env-gen.kr (asr 0 1 0.1) :gate gate :act :free)))
|
||||
(snd-step-4 (pan2.ar snd-step-3 pan amp)))
|
||||
(out.ar out snd-step-4)))
|
||||
|
||||
;;; strings
|
||||
|
||||
(defsynth tone-pluck ((freq 440) (amp 0.2))
|
||||
(out.ar 0 (* (saw.ar (let ((detune (* freq 0.01)))
|
||||
(list (- freq detune) (+ freq detune))))
|
||||
(env-gen.kr (perc 0.1 1.8)
|
||||
:level-scale amp
|
||||
:act :free))))
|
||||
|
||||
(defsynth prophet5pwmStrings ((out 0) (pan 0.0) (freq 440) (amp 1.0) (gate 1) (att 0.01)
|
||||
(rel 0) (sus 1) (dec 0.5) (lforate 10) (lfowidth 0.5) (cutoff 12000) (rq 0.5))
|
||||
(let* ((lfo (lf-tri.kr (mapcar (lambda (x) (* lforate x)) (list 1 1.01)) (make-list 2 :initial-element (rand.ir 0 2.0))))
|
||||
(pulse (pulse.ar (mapcar (lambda (x) (* freq x)) (list 1 1.01)) (+ (* lfo lfowidth) 0.5)))
|
||||
(filter (rlpf.ar pulse cutoff rq))
|
||||
(env (env-gen.ar (adsr att dec sus rel amp) :gate gate :act :free)))
|
||||
(out.ar out (pan2.ar (* (mix filter) env 0.5) pan))))
|
||||
|
||||
(defsynth strings ((out 0) (freq 440) (amp 1) (gate 1) (pan 0) (freqLag 0.2) (att 0.001) (dec 0.1) (sus 0.75) (rel 0.3)
|
||||
(rq 0.001) (combHarmonic 4) (sawHarmonic 1.5) (mix 0.33))
|
||||
(let* ((combFreq (/ 1 (* (lag.kr freq (/ freqLag 2)) combHarmonic)))
|
||||
(envelope (env-gen.kr (adsr att dec sus rel amp) :gate gate :act :free))
|
||||
(snd-step-1 (sync-saw.ar (* freq (range (white-noise.kr) (/ 1 1.025) 1.025)) (* freq sawHarmonic) 8))
|
||||
(snd-step-2 (+ (* snd-step-1 (- 1 mix)) (pink-noise.ar (* 180 mix))))
|
||||
(snd-step-3 (comb-l.ar snd-step-2 combFreq combFreq -1)) ; try 1 for decay as well
|
||||
(snd-step-4 (abs (resonz.ar snd-step-3 (lag.kr freq freqLag) rq)))
|
||||
(snd-step-5 (* snd-step-4 envelope))
|
||||
(snd-step-6 (limiter.ar snd-step-5 amp)))
|
||||
(out.ar out (pan2.ar snd-step-6 pan))))
|
||||
|
||||
(defsynth violin ((freq 440) (gate 1) (amp 1) (pan 0) (out 0) (att 0.1) (dec 0.1) (sus 0.5) (rel 0.1)
|
||||
(vRate 4.6) (vDepth 0.02) (vAtt 0.15) (vRateVar 0.25) (vDepthVar 0.05)
|
||||
(pwmVarRate 2) (pwmMin 0.7) (pwmMax 0.8) (pwmRate 5)
|
||||
(bridgeFreq 2500) (scratchDepth 0.15))
|
||||
(let* ((scratch (+ 1.025 (env-gen.kr (perc att (* 1.25 dec) scratchDepth))))
|
||||
(envelope (env-gen.kr (adsr att dec sus rel) :gate gate :act :free))
|
||||
(freq (vibrato.kr freq vRate vDepth (+ att dec) vAtt vRateVar vDepthVar))
|
||||
(pwm-step-1 (range (sin-osc.kr pwmRate (rand.ir 0.0 1.0)) pwmMin pwmMax))
|
||||
(pwm-step-2 (* pwm-step-1 (range (lf-noise2.kr pwmVarRate) 0.2 0.8)))
|
||||
(snd-step-1 (var-saw.ar (*
|
||||
(lag.kr freq)
|
||||
(range (lf-pulse.ar (* freq 1.5)) (/ 1 scratch) scratch))))
|
||||
(snd-step-2 (+ (* snd-step-1 0.7)
|
||||
(bpf.ar snd-step-1 bridgeFreq 2 2)))
|
||||
(snd-step-3 (* snd-step-2 amp envelope)))
|
||||
(out.ar out (pan2.ar snd-step-3 pan))))
|
||||
|
||||
;;; percussion
|
||||
|
||||
(defsynth kik ((freq 440) (out 0))
|
||||
(let* ((env (env-gen.kr (env (list 0 1 0) (list 0.001 1)) :act :free))
|
||||
(fenv (env-gen.kr (env (list 1 0) (list 0.25)) :level-scale freq))
|
||||
(sig (sin-osc.ar fenv 0 0.2)))
|
||||
(out.ar out (pan2.ar sig 0 env))))
|
||||
|
||||
(defsynth bdrum ((amp 0.5) (out 0) )
|
||||
(out.ar out (* amp (sin-osc.ar (line.ar 120 60 1) 0 (env-gen.ar (env (list 0 1 0) (list 0.005 0.5)) :act :free)))))
|
||||
|
||||
(defsynth snare ((amp 0.5) (out 0))
|
||||
(out.ar out (* amp (white-noise.ar (env-gen.ar (env (list 0 1 0.3 0) (list 0.005 0.01 0.5)) :act :free)))))
|
||||
|
||||
(defsynth hihat ((amp 0.5) (out 0))
|
||||
(out.ar out (* amp (hpf.ar (white-noise.ar 1) 10000) (env-gen.ar (env (list 0 1 0) (list 0.005 0.5)) :act :free))))
|
||||
|
||||
;;; bass
|
||||
|
||||
(defsynth acid0to3091 ((amp 0.5) (out 0) (gate 1) (freq 440) (pan 0) (att 0.001) (dec 0.5) (sus 0.1) (rel 0.5) (curve -4) (lagTime 0.12) (filterRange 6) (width 0.51) (rq 0.3))
|
||||
(let* ((freq (lag.kr freq lagTime))
|
||||
(ampEnv (env-gen.kr (adsr att dec sus rel amp 0) :gate gate))
|
||||
(filterEnv (env-gen.kr (adsr att (* 2 dec) (/ sus 2) (* 2 rel) (expt 2 filterRange) (list (* -1 curve) curve curve) 1) :gate gate :act :free))
|
||||
(sndStep1 (range (lf-pulse.ar freq 0.0 width) -1 1))
|
||||
(sndStep2 (rlpf.ar sndStep1 (* freq filterEnv) rq))
|
||||
(sndStep3 (* sndStep2 ampEnv)))
|
||||
(out.ar out (pan2.ar sndStep3 pan))))
|
||||
|
||||
(defsynth fmBass ((out 0) (freq 440) (gate 1) (amp 0.5) (pan 0) (att 0.01) (dec 0.3) (sus 0.4) (rel 0.1) (slideTime 0.17) (cutoff 1100) (width 0.15) (detune 1.005) (preamp 4))
|
||||
(let* ((env (env-gen.kr (adsr att dec sus rel) :gate gate :act :free))
|
||||
(freq (lag.kr freq slideTime))
|
||||
(sndStep1 (var-saw.ar (list freq (* freq detune)) 0 width preamp))
|
||||
(sndStep2 (distort (mix sndStep1)))
|
||||
(sndStep3 (* sndStep2 env))
|
||||
(sndStep4 (lpf.ar sndStep3 cutoff amp)))
|
||||
(out.ar out (pan2.ar sndStep4 pan))))
|
||||
|
||||
;;; air
|
||||
|
||||
;; doesn't seem to work, right?
|
||||
(defsynth waveguideFlute ((scl 0.2) (freq 440) (ipress 0.9) (ibreath 0.09) (ifeedbk1 0.4) (ifeedbk2 0.4)
|
||||
(dur 1) (gate 1) (amp 2))
|
||||
(let* ((sr (sample-rate.ir))
|
||||
(cr (control-rate.ir))
|
||||
(a-block (reciprocal cr))
|
||||
(ifqc freq)
|
||||
(kenv1 (env-gen.kr (env
|
||||
(list 0.0 (* 1.1 ipress) ipress ipress 0.0)
|
||||
(list 0.06 0.2 (- dur 0.46) 0.2)
|
||||
:linear))) ; noise envelope
|
||||
(kenv2 (env-gen.kr (env
|
||||
(list 0.0 amp amp 0.0)
|
||||
(list 0.1 (- dur 0.2) 0.1)
|
||||
:linear))) ; overall envelope
|
||||
(kenvibr (env-gen.kr (env
|
||||
(list 0.0 0.0 1 1 0.0)
|
||||
(list 0.5 0.5 (- dur 1.5) 0.5)
|
||||
:linear))) ; vibrato envelope
|
||||
(aflow1 (lf-clip-noise.ar sr kenv1)) ; create air flow and vibrato
|
||||
(kvibr (sin-osc.ar 5 0 (* 0.1 kenvibr)))
|
||||
|
||||
(asum1 (+ (* ibreath aflow1) kenv1 kvibr))
|
||||
(afqc (+ (reciprocal ifqc) (/ ifqc 12000000) (- (/ asum1 20000)) (- (/ 9 sr)) (- a-block)))
|
||||
(fdbckArray (local-in.ar 1))
|
||||
(aflute1 fdbckArray)
|
||||
(asum2 (+ asum1 (* aflute1 ifeedbk1)))
|
||||
(ax (delay-c.ar asum2
|
||||
(- (reciprocal ifqc) (* a-block 0.5)) ; original has strange asum1/ifqc/cr thing, is that consequtive division, or third is on top?
|
||||
(* afqc 0.5)))
|
||||
(apoly (- ax (cubed ax)))
|
||||
(asum3 (+ apoly (* aflute1 ifeedbk2)))
|
||||
(avalue (lpf.ar asum3 2000))
|
||||
(aflute2 (delay-c.ar avalue (- (reciprocal ifqc) a-block) afqc))
|
||||
(fdbckArray (list aflute2))
|
||||
;; (no-name (local-out.ar fdbckArray)) ; does that work at all? are there side effects?
|
||||
(signalOut avalue))
|
||||
(local-out.ar fdbckArray)
|
||||
(offset-out.ar 0 (list (* signalOut kenv2) (* signalOut kenv2)))))
|
||||
|
||||
;;; simplistic
|
||||
|
||||
(defsynth default ((gate 1) (freq 440) (out 0))
|
||||
(let* ((env (env-gen.kr (asr 0.01 1 0.1) :gate gate :act :free))
|
||||
(sig (sin-osc.ar freq 0 0.2)))
|
||||
(out.ar out (pan2.ar sig 0 env))))
|
||||
|
||||
(defsynth tone-buzz ((freq 440) (amp 0.2) (gate 1))
|
||||
(out.ar 0 (*
|
||||
(saw.ar (let ((detune (* freq 0.01)))
|
||||
(list (- freq detune) (+ freq detune)))
|
||||
(/ amp 2))
|
||||
(env-gen.kr (asr 0 1 0.1) :gate gate :act :free))))
|
||||
|
||||
(defsynth tone-pluck ((freq 440) (amp 0.2))
|
||||
(out.ar 0 (* (saw.ar (let ((detune (* freq 0.01)))
|
||||
(list (- freq detune) (+ freq detune))))
|
||||
(env-gen.kr (perc 0.1 1.8)
|
||||
:level-scale amp
|
||||
:act :free))))
|
||||
|
||||
(defsynth sine-wave ((note 60) (freq 400))
|
||||
(let* ((freq (midicps note))
|
||||
(sig (sin-osc.ar freq 0 .2)))
|
||||
(out.ar 0 sig)))
|
||||
Reference in New Issue
Block a user